#ifndef _WIN32 #include #endif #include #include #include #include #include "coff.h" static const char* const usage = "usage: blob-object-coff
\n"; int main(int argc, char** argv) { if (argc < 5) { fprintf(stderr, "not enough arguments\n%s", usage); return 1; } if (argc > 5) { fprintf(stderr, "too many arguments\n%s", usage); return 1; } char* output_file_name = argv[1]; char* section_name = argv[2]; uint32_t section_name_size = strlen(section_name); char* symbol_name = argv[3]; uint32_t symbol_name_size = strlen(symbol_name) + 1; char* blob_file_name = argv[4]; if (section_name_size > 8) { fprintf(stderr, "section name is too long for COFF\n"); return 1; } FILE* blob_file = fopen(blob_file_name, "rb"); if (blob_file == NULL) { goto blob_fail; } if (fseek(blob_file, 0, SEEK_END) != 0) { goto blob_fail; } long blob_size = ftell(blob_file); if (blob_size == -1L) { goto blob_fail; } rewind(blob_file); void* blob = malloc(blob_size); if (fread(blob, 1, blob_size, blob_file) < blob_size) { goto blob_fail; } fclose(blob_file); FILE* output_file = fopen(output_file_name, "wb"); if (output_file == NULL) { goto output_fail; } uint32_t size_name_size = symbol_name_size + 5; uint32_t blob_name_size = symbol_name_size; uint32_t strtab_size_name_off = 4; uint32_t strtab_blob_name_off = strtab_size_name_off + size_name_size; uint32_t strtab_size = 4 + strtab_blob_name_off + blob_name_size; uint32_t coff_header_off = 0; uint32_t section_header_off = sizeof(struct coff_header); uint32_t symbol_header_off = section_header_off + sizeof(struct coff_section); uint32_t size_symbol_off = symbol_header_off; uint32_t blob_symbol_off = size_symbol_off + COFF_SYMTAB_SIZE; uint32_t string_table_off = blob_symbol_off + COFF_SYMTAB_SIZE; uint32_t blob_size_off = string_table_off + strtab_size; uint32_t blob_data_off = blob_size_off + sizeof(uint64_t); uint32_t file_end_off = blob_data_off + blob_size; uint8_t* data = calloc(file_end_off, 1); time_t now = time(0); *(struct coff_header*) (data + coff_header_off) = (struct coff_header) { .magic = MAGIC_AMD64, .nscns = 1, .timdat = (uint32_t) now, .symptr = symbol_header_off, .nsyms = 2, .opthdr = 0, .flags = 0, }; struct coff_section data_section = { .name = 0, .paddr = 0, .vaddr = 0, .size = sizeof(uint64_t) + blob_size, .scnptr = blob_size_off, .relptr = 0, .lnnoptr = 0, .nreloc = 0, .nlnno = 0, .flags = STYP_DATA, }; strncpy(data_section.name, section_name, section_name_size); memcpy(data + section_header_off, &data_section, sizeof(struct coff_section)); struct coff_symtab size_symbol = { .zeroes = 0, .name = strtab_size_name_off, .value = 0, .scnum = 1, .type = 0, .sclass = C_EXT, .numaux = 0, }; memcpy(data + size_symbol_off, &size_symbol, COFF_SYMTAB_SIZE); struct coff_symtab blob_symbol = { .zeroes = 0, .name = strtab_blob_name_off, .value = sizeof(uint64_t), .scnum = 1, .type = 0, .sclass = C_EXT, .numaux = 0, }; memcpy(data + blob_symbol_off, &blob_symbol, COFF_SYMTAB_SIZE); memcpy(data + string_table_off, &strtab_size, 4); memcpy( data + string_table_off + strtab_size_name_off, symbol_name, size_name_size - 1 ); memcpy( data + string_table_off + strtab_size_name_off + symbol_name_size - 1, "_size\0", 6 ); memcpy( data + string_table_off + strtab_blob_name_off, symbol_name, blob_name_size ); *(uint64_t*) (data + blob_size_off) = blob_size; memcpy(data + blob_data_off, blob, blob_size); if (fwrite(data, 1, file_end_off, output_file) < file_end_off) { goto output_fail; } if (fflush(output_file) != 0) { goto output_fail; } return 0; blob_fail: fprintf( stderr, "failed to read blob file %s: %s\n%s", blob_file_name, strerror(errno), usage ); return 1; output_fail: fprintf( stderr, "failed to write output file %s: %s\n %s", output_file_name, strerror(errno), usage ); return 1; }