blob-object/subprojects/blob-object-coff/src/main.c

175 lines
4.6 KiB
C

#ifndef _WIN32
#include <errno.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "coff.h"
static const char* const usage =
"usage: blob-object-coff <output file> <section name> <symbol name> <blob file>\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;
}