#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
static void libsof_read_header(FILE* file, sof_file_t* obj);
static void libsof_read_symbols(FILE* file, sof_file_t* obj);
static void libsof_write_strings(FILE* file, sof_file_t* obj);
static void libsof_write_data(FILE* file, sof_file_t* obj);
static void libsof_write_code(FILE* file, sof_file_t* obj);
-//static bool is_big_endian(void);
+static void* libsof_get_segment_addr(void* segment, size_t seg_size, size_t el_size, size_t offset);
+static size_t libsof_add_to_segment(void** segment, size_t* seg_size, void const* data, size_t length);
/******************************************************************************
* Functions for Reading an SOF file
*****************************************************************************/
-sof_file_t* libsof_read(const char* fname)
+sof_file_t* libsof_read_obj(char const* fname)
{
sof_file_t* obj = NULL;
/* Open the file for reading */
{
if (obj->header->sym_tbl_sz)
{
- size_t sz = obj->header->sym_tbl_sz * sizeof(sof_st_entry_t);
- obj->symbols = (sof_st_entry_t*)malloc(sz);
- fread(obj->symbols, sizeof(sof_st_entry_t), obj->header->sym_tbl_sz, file);
+ obj->symbols = (sof_st_entry_t*)malloc( obj->header->sym_tbl_sz );
+ fread(obj->symbols, sizeof(uint8_t), obj->header->sym_tbl_sz, file);
}
}
{
if (obj->header->sym_str_tbl_sz)
{
- obj->str_tbl = (uint8_t*)malloc( obj->header->sym_str_tbl_sz );
- fread( obj->str_tbl, sizeof(uint8_t), obj->header->sym_str_tbl_sz, file);
+ obj->strings = (char*)malloc( obj->header->sym_str_tbl_sz );
+ fread( obj->strings, sizeof(uint8_t), obj->header->sym_str_tbl_sz, file);
}
}
{
if (obj->header->code_sz)
{
- size_t sz = obj->header->code_sz * sizeof(uint32_t);
- obj->code = (uint32_t*)malloc(sz);
- fread(obj->code, sizeof(uint32_t), obj->header->code_sz, file);
+ obj->code = (uint32_t*)malloc( obj->header->code_sz );
+ fread(obj->code, sizeof(uint8_t), obj->header->code_sz, file);
}
}
/******************************************************************************
* Functions for Writing an SOF file
*****************************************************************************/
-bool libsof_write(const char* fname, sof_file_t* obj)
+bool libsof_write_obj(sof_file_t* obj, char const* fname)
{
bool ret = false;
/* Open the file for reading */
- FILE* fhndl = fopen(fname,"rb");
+ FILE* fhndl = fopen(fname,"wb");
/* if the file was successfully opened */
if (fhndl)
{
{
if (obj->header->sym_tbl_sz)
{
- fwrite(obj->symbols, sizeof(sof_st_entry_t), obj->header->sym_tbl_sz, file);
+ fwrite(obj->symbols, sizeof(sof_st_entry_t), obj->header->sym_tbl_sz / sizeof(sof_st_entry_t), file);
}
}
{
if (obj->header->sym_str_tbl_sz)
{
- fwrite( obj->str_tbl, sizeof(uint8_t), obj->header->sym_str_tbl_sz, file);
+ fwrite( obj->strings, sizeof(uint8_t), obj->header->sym_str_tbl_sz, file);
}
}
{
if (obj->header->code_sz)
{
- fwrite(obj->code, sizeof(uint32_t), obj->header->code_sz, file);
+ fwrite(obj->code, sizeof(uint32_t), obj->header->code_sz / sizeof(uint32_t), file);
}
}
+/******************************************************************************
+ * Functions for Creating and Modifying SOF files
+ *****************************************************************************/
+sof_file_t* libsof_new_obj(void)
+{
+ sof_file_t* obj = (sof_file_t*)calloc(1,sizeof(sof_file_t));
+ obj->header = (sof_header_t*)calloc(1,sizeof(sof_header_t));
+ obj->header->version = SOF_VERSION;
+ return obj;
+}
+
+void libsof_free_obj(sof_file_t* obj)
+{
+ free(obj->header);
+ free(obj->symbols);
+ free(obj->strings);
+ free(obj->data);
+ free(obj->code);
+ free(obj);
+}
+
+size_t libsof_get_symbol_table_size(sof_file_t* obj)
+{
+ return obj->header->sym_tbl_sz;
+}
+
+size_t libsof_get_string_table_size(sof_file_t* obj)
+{
+ return obj->header->sym_str_tbl_sz;
+}
+
+size_t libsof_get_data_segment_size(sof_file_t* obj)
+{
+ return obj->header->data_sz;
+}
+
+size_t libsof_get_code_segment_size(sof_file_t* obj)
+{
+ return obj->header->code_sz;
+}
+
+size_t libsof_get_num_symbols(sof_file_t* obj)
+{
+ return obj->header->sym_tbl_sz / sizeof(sof_st_entry_t);
+}
+
+size_t libsof_add_symbol(sof_file_t* obj, const char* name, uint32_t value, uint32_t size, uint32_t info)
+{
+ size_t str_idx = libsof_add_string(obj, name);
+ return libsof_add_st_entry(obj, str_idx, value, size, info);
+}
+
+size_t libsof_add_st_entry(sof_file_t* obj, uint32_t name, uint32_t value, uint32_t size, uint32_t info)
+{
+ sof_st_entry_t new_sym = { name, value, size, info };
+ return libsof_add_to_segment( (void**)&(obj->symbols), &(obj->header->sym_tbl_sz), &new_sym, sizeof(sof_st_entry_t) );
+}
+
+sof_st_entry_t const* libsof_get_st_entry(sof_file_t* obj, size_t offset)
+{
+ return libsof_get_segment_addr( obj->symbols, obj->header->sym_tbl_sz, sizeof(sof_st_entry_t), offset);
+}
+
+size_t libsof_add_string(sof_file_t* obj, char const* name)
+{
+ return libsof_add_to_segment( (void**)&(obj->strings), &(obj->header->sym_str_tbl_sz), name, strlen(name) + 1 );
+}
+
+char const* libsof_get_string(sof_file_t* obj, size_t offset)
+{
+ return libsof_get_segment_addr( obj->strings, obj->header->sym_str_tbl_sz, sizeof(char), offset);
+}
+
+size_t libsof_add_data(sof_file_t* obj, uint8_t const* data, size_t length)
+{
+ return libsof_add_to_segment( (void**)&(obj->data), &(obj->header->data_sz), data, length );
+}
+
+uint8_t const* libsof_get_data(sof_file_t* obj, size_t offset)
+{
+ return libsof_get_segment_addr( obj->data, obj->header->data_sz, sizeof(uint8_t), offset);
+}
+
+size_t libsof_add_code(sof_file_t* obj, uint32_t const* code, size_t length)
+{
+ return libsof_add_to_segment( (void**)&(obj->code), &(obj->header->code_sz), code, length * sizeof(uint32_t) );
+}
+
+uint32_t const* libsof_get_code(sof_file_t* obj, size_t offset)
+{
+ return libsof_get_segment_addr( obj->code, obj->header->code_sz, sizeof(uint32_t), offset);
+}
+
/******************************************************************************
* Static Helper Functions
*****************************************************************************/
-//static bool is_big_endian(void)
-//{
-// union {
-// uint32_t i;
-// uint8_t c[4];
-// } bint = { 0x01020304 };
-// return bint.c[0] == 1;
-//}
+static void* libsof_get_segment_addr(void* segment, size_t seg_size, size_t el_size, size_t offset)
+{
+ void* addr = NULL;
+ size_t addr_offset = offset * el_size;
+ if (addr_offset < seg_size)
+ {
+ addr = segment + addr_offset;
+ }
+ return addr;
+}
+
+static size_t libsof_add_to_segment(void** segment, size_t* seg_size, void const* data, size_t length)
+{
+ size_t offset = *(seg_size);
+ *(seg_size) = offset + length;
+ *(segment) = realloc(*(segment), *(seg_size));
+ memcpy( *(segment) + offset, data, length );
+ return offset;
+}
--- /dev/null
+#include <stdio.h>
+#include <libsof.h>
+
+#define GET_VERSION_YEAR(version) (version >> 16)
+#define GET_VERSION_MONTH(version) ((version >> 8) & 0xFF)
+#define GET_VERSION_DAY(version) (version & 0xFF)
+
+void print_obj(sof_file_t* obj);
+void print_hex(char const* header, uint8_t const* buffer, size_t length);
+
+void create_obj_file(char* fname)
+{
+ sof_file_t* obj = libsof_new_obj();
+
+ libsof_add_symbol(obj, "foo", 0x11223344, 0x22222222, 0x33333333);
+
+ uint8_t data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
+ libsof_add_data(obj, data, 16);
+ libsof_add_data(obj, data, 16);
+ libsof_add_data(obj, data, 16);
+
+ uint32_t code[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
+ libsof_add_code(obj, code, 16);
+ libsof_add_code(obj, code, 16);
+ libsof_add_code(obj, code, 16);
+
+ libsof_write_obj(obj,fname);
+ libsof_free_obj(obj);
+}
+
+void print_obj(sof_file_t* obj)
+{
+ /* print header metadata */
+ printf("SOF Version:\t%#x (%d/%d/%d)\n",
+ obj->header->version,
+ GET_VERSION_DAY(obj->header->version),
+ GET_VERSION_MONTH(obj->header->version),
+ GET_VERSION_YEAR(obj->header->version));
+ printf("Symbol Table:\t%d bytes\n", obj->header->sym_tbl_sz);
+ printf("String Table:\t%d bytes\n", obj->header->sym_str_tbl_sz);
+ printf("Data Size:\t%d bytes\n", obj->header->data_sz);
+ printf("Code Size:\t%d bytes\n", obj->header->code_sz);
+
+ /* print symbol table */
+ printf("\nIndex\tValue\t\tSize\t\tInfo\t\tName\n");
+ for(size_t i = 0; i < libsof_get_num_symbols(obj); i++)
+ {
+ sof_st_entry_t const* symbol = libsof_get_st_entry(obj,i);
+ char const* name = libsof_get_string(obj,symbol->name);
+ printf("[%d]\t%#x\t%#x\t%#x\t%s\n", i, symbol->value, symbol->size, symbol->info, name);
+ }
+
+ /* print segments as hex listing */
+ print_hex("Data Segment", (uint8_t const *)libsof_get_data(obj,0), libsof_get_data_segment_size(obj));
+ print_hex("Code Segment", (uint8_t const *)libsof_get_code(obj,0), libsof_get_code_segment_size(obj));
+}
+
+void print_hex(char const* header, uint8_t const* buffer, size_t length)
+{
+ printf("\n\n%s\n",header);
+ printf("----------------------------------------------------------");
+ for(size_t i = 0; i < length; i++)
+ {
+ if ((i%16) == 0)
+ {
+ printf("\n0x%04x\t", i);
+ }
+ else if ((i%4) == 0)
+ {
+ printf(" ");
+ }
+ printf("%02x ", buffer[i]);
+ }
+}
+
+int main(int argc, char** argv)
+{
+ if (argc == 1)
+ {
+ printf("%s: no input files.\n", argv[0]);
+ }
+ else
+ {
+ create_obj_file(argv[1]);
+ for (uint32_t i = 1; i < argc; i++)
+ {
+ printf("\nFilename:\t%s\n", argv[i]);
+ sof_file_t* obj = libsof_read_obj(argv[i]);
+ print_obj(obj);
+ libsof_free_obj(obj);
+ }
+ }
+}
+