summaryrefslogtreecommitdiff
path: root/ao-tools/lib
diff options
context:
space:
mode:
Diffstat (limited to 'ao-tools/lib')
-rw-r--r--ao-tools/lib/Makefile.am4
-rw-r--r--ao-tools/lib/ao-elf.c94
-rw-r--r--ao-tools/lib/ao-elf.h13
-rw-r--r--ao-tools/lib/ao-hex.c286
-rw-r--r--ao-tools/lib/ao-hex.h16
5 files changed, 346 insertions, 67 deletions
diff --git a/ao-tools/lib/Makefile.am b/ao-tools/lib/Makefile.am
index 868b64f1..ca32e121 100644
--- a/ao-tools/lib/Makefile.am
+++ b/ao-tools/lib/Makefile.am
@@ -43,4 +43,6 @@ libao_tools_a_SOURCES = \
ao-hex.c \
ao-hex.h \
ao-elf.c \
- ao-elf.h
+ ao-elf.h \
+ ao-verbose.c \
+ ao-verbose.h
diff --git a/ao-tools/lib/ao-elf.c b/ao-tools/lib/ao-elf.c
index 932dc853..99b37210 100644
--- a/ao-tools/lib/ao-elf.c
+++ b/ao-tools/lib/ao-elf.c
@@ -27,21 +27,26 @@
#include <fcntl.h>
#include "ao-elf.h"
#include "ao-hex.h"
+#include "ao-verbose.h"
/*
* Look through the Elf file for symbols that can be adjusted before
* the image is written to the device
*/
-static bool
-find_symbols (Elf *e, struct ao_elf_sym *symbols, int num_symbols)
+static struct ao_sym *
+load_symbols (Elf *e, int *num_symbolsp)
{
Elf_Scn *scn;
Elf_Data *symbol_data = NULL;
GElf_Shdr shdr;
GElf_Sym sym;
- int i, symbol_count, s;
+ int i, symbol_count;
char *symbol_name;
size_t shstrndx;
+ struct ao_sym *symbols = NULL;
+ struct ao_sym *symbol;
+ int num_symbols = 0;
+ int size_symbols = 0;
if (elf_getshdrstrndx(e, &shstrndx) < 0)
return false;
@@ -64,23 +69,46 @@ find_symbols (Elf *e, struct ao_elf_sym *symbols, int num_symbols)
}
if (!symbol_data)
- return false;
+ return NULL;
for (i = 0; i < symbol_count; i++) {
gelf_getsym(symbol_data, i, &sym);
symbol_name = elf_strptr(e, shdr.sh_link, sym.st_name);
+ if (!symbol_name[0])
+ continue;
- for (s = 0; s < num_symbols; s++)
- if (!strcmp (symbols[s].name, symbol_name)) {
- symbols[s].addr = sym.st_value;
- symbols[s].found = true;
- }
+ if (num_symbols == size_symbols) {
+ struct ao_sym *new_symbols;
+ int new_size;
+
+ if (!size_symbols)
+ new_size = 16;
+ else
+ new_size = size_symbols * 2;
+ new_symbols = realloc(symbols, new_size * sizeof (struct ao_sym));
+ if (!new_symbols)
+ goto bail;
+
+ symbols = new_symbols;
+ size_symbols = new_size;
+ }
+ symbol = &symbols[num_symbols];
+ memset(symbol, 0, sizeof (struct ao_sym));
+ symbol->name = strdup(symbol_name);
+ if (!symbol->name)
+ goto bail;
+ symbol->addr = sym.st_value;
+ ao_printf(AO_VERBOSE_EXE, "Add symbol %s: %08x\n", symbol->name, symbol->addr);
+ num_symbols++;
}
- for (s = 0; s < num_symbols; s++)
- if (symbols[s].required && !symbols[s].found)
- return false;
- return true;
+ *num_symbolsp = num_symbols;
+ return symbols;
+bail:
+ for (i = 0; i < num_symbols; i++)
+ free(symbols[i].name);
+ free(symbols);
+ return NULL;
}
static uint32_t
@@ -173,7 +201,9 @@ get_load(Elf *e)
GElf_Phdr phdr;
GElf_Addr sh_paddr;
struct ao_hex_image *load = NULL;
+#if 0
char *section_name;
+#endif
size_t nshdr;
size_t s;
@@ -201,27 +231,29 @@ get_load(Elf *e)
/* Get the associated file section */
#if 0
- printf ("offset %08x vaddr %08x paddr %08x filesz %08x memsz %08x\n",
- (uint32_t) phdr.p_offset,
- (uint32_t) phdr.p_vaddr,
- (uint32_t) phdr.p_paddr,
- (uint32_t) phdr.p_filesz,
- (uint32_t) phdr.p_memsz);
+ fprintf (stderr, "offset %08x vaddr %08x paddr %08x filesz %08x memsz %08x\n",
+ (uint32_t) phdr.p_offset,
+ (uint32_t) phdr.p_vaddr,
+ (uint32_t) phdr.p_paddr,
+ (uint32_t) phdr.p_filesz,
+ (uint32_t) phdr.p_memsz);
#endif
for (s = 0; s < nshdr; s++) {
scn = elf_getscn(e, s);
if (!scn) {
- printf ("getscn failed\n");
+ fprintf (stderr, "getscn failed\n");
abort();
}
if (gelf_getshdr(scn, &shdr) != &shdr) {
- printf ("gelf_getshdr failed\n");
+ fprintf (stderr, "gelf_getshdr failed\n");
abort();
}
+#if 0
section_name = elf_strptr(e, shstrndx, shdr.sh_name);
+#endif
if (phdr.p_offset <= shdr.sh_offset && shdr.sh_offset < phdr.p_offset + phdr.p_filesz) {
@@ -230,11 +262,13 @@ get_load(Elf *e)
sh_paddr = phdr.p_paddr + shdr.sh_offset - phdr.p_offset;
- printf ("\tsize %08x rom %08x exec %08x %s\n",
- (uint32_t) shdr.sh_size,
- (uint32_t) sh_paddr,
- (uint32_t) shdr.sh_addr,
- section_name);
+#if 0
+ fprintf (stderr, "\tsize %08x rom %08x exec %08x %s\n",
+ (uint32_t) shdr.sh_size,
+ (uint32_t) sh_paddr,
+ (uint32_t) shdr.sh_addr,
+ section_name);
+#endif
data = elf_getdata(scn, NULL);
@@ -252,7 +286,7 @@ get_load(Elf *e)
*/
struct ao_hex_image *
-ao_load_elf(char *name, struct ao_elf_sym *symbols, int num_symbols)
+ao_load_elf(char *name, struct ao_sym **symbols, int *num_symbols)
{
int fd;
Elf *e;
@@ -278,10 +312,8 @@ ao_load_elf(char *name, struct ao_elf_sym *symbols, int num_symbols)
if (elf_getshdrstrndx(e, &shstrndx) != 0)
return NULL;
- if (!find_symbols(e, symbols, num_symbols)) {
- fprintf (stderr, "Cannot find required symbols\n");
- return NULL;
- }
+ if (symbols)
+ *symbols = load_symbols(e, num_symbols);
image = get_load(e);
if (!image) {
diff --git a/ao-tools/lib/ao-elf.h b/ao-tools/lib/ao-elf.h
index f3a2358c..0f79d142 100644
--- a/ao-tools/lib/ao-elf.h
+++ b/ao-tools/lib/ao-elf.h
@@ -22,18 +22,7 @@
#include <gelf.h>
#include "ao-hex.h"
-struct ao_elf_sym {
- unsigned addr;
- unsigned default_addr;
- char *name;
- bool required;
- bool found;
-};
-
struct ao_hex_image *
-ao_load_elf(char *name, struct ao_elf_sym *symbols, int num_symbols);
-
-int
-ao_elf_find_symbols (Elf *e, struct ao_elf_sym *symbols, int num_symbols);
+ao_load_elf(char *name, struct ao_sym **symbols, int *num_symbols);
#endif /* _AO_ELF_H_ */
diff --git a/ao-tools/lib/ao-hex.c b/ao-tools/lib/ao-hex.c
index 85acc07f..5cfc63c1 100644
--- a/ao-tools/lib/ao-hex.c
+++ b/ao-tools/lib/ao-hex.c
@@ -20,8 +20,10 @@
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
#include <string.h>
#include "ao-hex.h"
+#include "ao-verbose.h"
struct ao_hex_input {
FILE *file;
@@ -118,7 +120,7 @@ ao_hex_read_record(struct ao_hex_input *input)
while (state != read_done) {
c = getc(input->file);
- if (c == EOF && state != read_white) {
+ if (c == EOF && state != read_white && state != read_marker) {
ao_hex_error(input, "Unexpected EOF");
goto bail;
}
@@ -128,6 +130,8 @@ ao_hex_read_record(struct ao_hex_input *input)
input->line++;
switch (state) {
case read_marker:
+ if (c == EOF)
+ return NULL;
if (c != ':') {
ao_hex_error(input, "Missing ':'");
goto bail;
@@ -246,13 +250,20 @@ ao_hex_file_read(FILE *file, char *name)
int done = 0;
hex = calloc(sizeof (struct ao_hex_file) + sizeof (struct ao_hex_record *), 1);
+ if (!hex)
+ return NULL;
input.name = name;
input.line = 1;
input.file = file;
while (!done) {
record = ao_hex_read_record(&input);
- if (!record)
- goto bail;
+ if (!record) {
+ if (feof(input.file)) {
+ done = 1;
+ break;
+ } else
+ goto bail;
+ }
if (hex->nrecord == srecord) {
srecord *= 2;
newhex = realloc(hex,
@@ -263,8 +274,6 @@ ao_hex_file_read(FILE *file, char *name)
hex = newhex;
}
hex->records[hex->nrecord++] = record;
- if (record->type == AO_HEX_RECORD_EOF)
- done = 1;
}
return hex;
@@ -273,6 +282,92 @@ bail:
return NULL;
}
+static struct ao_sym *
+load_symbols(struct ao_hex_file *hex,
+ int *num_symbolsp)
+{
+ uint32_t extended_addr;
+ uint32_t addr;
+ int i;
+ struct ao_hex_record *record;
+ struct ao_sym *symbols = NULL;
+ struct ao_sym *symbol;
+ int num_symbols = 0;
+ int size_symbols = 0;
+
+ extended_addr = 0;
+ for (i = 0; i < hex->nrecord; i++) {
+ record = hex->records[i];
+ switch (record->type) {
+ case AO_HEX_RECORD_NORMAL:
+ addr = extended_addr + record->address;
+ break;
+ case AO_HEX_RECORD_EOF:
+ break;
+ case AO_HEX_RECORD_EXTENDED_ADDRESS_4:
+ if (record->length != 2)
+ goto bail;
+ extended_addr = ((record->data[0] << 8) | record->data[1]) << 4;
+ break;
+ case AO_HEX_RECORD_EXTENDED_ADDRESS_8:
+ if (record->length != 2)
+ goto bail;
+ extended_addr = (record->data[0] << 24) | (record->data[1] << 16);
+ break;
+ case AO_HEX_RECORD_SYMBOL:
+ addr = extended_addr + record->address;
+ if (num_symbols == size_symbols) {
+ struct ao_sym *new_symbols;
+ int new_size;
+
+ if (!size_symbols)
+ new_size = 16;
+ else
+ new_size = size_symbols * 2;
+ new_symbols = realloc(symbols, new_size * sizeof (struct ao_sym));
+ if (!new_symbols)
+ goto bail;
+
+ symbols = new_symbols;
+ size_symbols = new_size;
+ }
+ symbol = &symbols[num_symbols];
+ memset(symbol, 0, sizeof (struct ao_sym));
+ symbol->name = calloc(record->length + 1, 1);
+ if (!symbol->name)
+ goto bail;
+ memcpy(symbol->name, record->data, record->length);
+ symbol->addr = addr;
+ ao_printf(AO_VERBOSE_EXE, "Add symbol %s: %08x\n", symbol->name, symbol->addr);
+ num_symbols++;
+ break;
+ }
+ }
+ *num_symbolsp = num_symbols;
+ return symbols;
+bail:
+ for (i = 0; i < num_symbols; i++)
+ free(symbols[i].name);
+ free(symbols);
+ return NULL;
+}
+
+static void
+ao_hex_record_set_checksum(struct ao_hex_record *record)
+{
+ uint8_t cksum = 0;
+ int i;
+
+ cksum += record->length;
+ cksum += record->address >> 8;
+ cksum += record->address;
+ cksum += record->type;
+ for (i = 0; i < record->length; i++)
+ cksum += record->data[i];
+
+ record->checksum = -cksum;
+}
+
struct ao_hex_image *
ao_hex_image_create(struct ao_hex_file *hex)
{
@@ -286,6 +381,8 @@ ao_hex_image_create(struct ao_hex_file *hex)
int length;
+ /* Find the address bounds of the file
+ */
base = 0xffffffff;
bound = 0x0;
extended_addr = 0;
@@ -293,7 +390,7 @@ ao_hex_image_create(struct ao_hex_file *hex)
uint32_t r_bound;
record = hex->records[i];
switch (record->type) {
- case 0:
+ case AO_HEX_RECORD_NORMAL:
addr = extended_addr + record->address;
r_bound = addr + record->length;
if (addr < base)
@@ -301,20 +398,21 @@ ao_hex_image_create(struct ao_hex_file *hex)
if (r_bound > bound)
bound = r_bound;
break;
- case 1:
+ case AO_HEX_RECORD_EOF:
break;
- case 2:
+ case AO_HEX_RECORD_EXTENDED_ADDRESS_4:
if (record->length != 2)
return NULL;
extended_addr = ((record->data[0] << 8) | record->data[1]) << 4;
break;
- case 4:
+ case AO_HEX_RECORD_EXTENDED_ADDRESS_8:
if (record->length != 2)
return NULL;
- extended_addr = ((record->data[0] << 8) | record->data[1]) << 16;
+ extended_addr = (record->data[0] << 24) | (record->data[1] << 16);
+ break;
+ case AO_HEX_RECORD_SYMBOL:
break;
}
-
}
length = bound - base;
image = calloc(sizeof(struct ao_hex_image) + length, 1);
@@ -327,18 +425,20 @@ ao_hex_image_create(struct ao_hex_file *hex)
for (i = 0; i < hex->nrecord; i++) {
record = hex->records[i];
switch (record->type) {
- case 0:
+ case AO_HEX_RECORD_NORMAL:
addr = extended_addr + record->address;
offset = addr - base;
memcpy(image->data + offset, record->data, record->length);
break;
- case 1:
+ case AO_HEX_RECORD_EOF:
break;
- case 2:
+ case AO_HEX_RECORD_EXTENDED_ADDRESS_4:
extended_addr = ((record->data[0] << 8) | record->data[1]) << 4;
break;
- case 4:
- extended_addr = ((record->data[0] << 8) | record->data[1]) << 16;
+ case AO_HEX_RECORD_EXTENDED_ADDRESS_8:
+ extended_addr = (record->data[0] << 24) | (record->data[1] << 16);
+ break;
+ case AO_HEX_RECORD_SYMBOL:
break;
}
}
@@ -362,23 +462,165 @@ ao_hex_image_equal(struct ao_hex_image *a, struct ao_hex_image *b)
}
struct ao_hex_image *
-ao_hex_load(char *filename)
+ao_hex_load(char *filename, struct ao_sym **symbols, int *num_symbolsp)
{
- FILE *file;
+ FILE *file;
struct ao_hex_file *hex_file;
- struct ao_hex_image *hex_image;
+ struct ao_hex_image *hex_image;
file = fopen (filename, "r");
if (!file)
- return 0;
+ return NULL;
hex_file = ao_hex_file_read(file, filename);
fclose(file);
if (!hex_file)
- return 0;
+ return NULL;
hex_image = ao_hex_image_create(hex_file);
if (!hex_image)
- return 0;
+ return NULL;
+
+ if (symbols)
+ *symbols = load_symbols(hex_file, num_symbolsp);
+
ao_hex_file_free(hex_file);
return hex_image;
}
+
+#define BYTES_PER_RECORD 32
+
+static struct ao_hex_file *
+ao_hex_file_create(struct ao_hex_image *image, struct ao_sym *symbols, int num_symbols)
+{
+ /* split data into n-byte-sized chunks */
+ uint32_t data_records = (image->length + BYTES_PER_RECORD-1) / BYTES_PER_RECORD;
+ /* extended address and data for each block, EOF, address and data for each symbol */
+ uint32_t total_records = data_records * 2 + 1 + num_symbols * 2;
+ uint32_t offset;
+ uint32_t address;
+ uint32_t length;
+ char *name;
+ struct ao_hex_file *hex_file;
+ int nrecord = 0;
+ int s;
+ struct ao_hex_record *record;
+
+ hex_file = calloc(sizeof (struct ao_hex_file) + sizeof (struct ao_hex_record *) * total_records, 1);
+ if (!hex_file)
+ return NULL;
+
+ /* Add the data
+ */
+ for (offset = 0; offset < image->length; offset += BYTES_PER_RECORD) {
+ uint32_t address = image->address + offset;
+ uint32_t length = image->length - offset;
+
+ if (length > BYTES_PER_RECORD)
+ length = BYTES_PER_RECORD;
+
+ record = calloc(sizeof (struct ao_hex_record) + 2, 1);
+ record->type = AO_HEX_RECORD_EXTENDED_ADDRESS_8;
+ record->address = 0;
+ record->length = 2;
+ record->data[0] = address >> 24;
+ record->data[1] = address >> 16;
+ ao_hex_record_set_checksum(record);
+
+ hex_file->records[nrecord++] = record;
+
+ record = calloc(sizeof (struct ao_hex_record) + length, 1);
+ record->type = AO_HEX_RECORD_NORMAL;
+ record->address = address;
+ record->length = length;
+ memcpy(record->data, image->data + offset, length);
+ ao_hex_record_set_checksum(record);
+
+ hex_file->records[nrecord++] = record;
+ }
+
+ /* Stick an EOF after the data
+ */
+ record = calloc(sizeof (struct ao_hex_record), 1);
+ record->type = AO_HEX_RECORD_EOF;
+ record->address = 0;
+ record->length = 0;
+ record->data[0] = 0;
+ record->data[1] = 0;
+ ao_hex_record_set_checksum(record);
+
+ hex_file->records[nrecord++] = record;
+
+ /* Add the symbols
+ */
+
+ for (s = 0; s < num_symbols; s++) {
+
+ name = symbols[s].name;
+ address = symbols[s].addr;
+ length = strlen (name);
+
+ record = calloc(sizeof (struct ao_hex_record) + 2, 1);
+ record->type = AO_HEX_RECORD_EXTENDED_ADDRESS_8;
+ record->address = 0;
+ record->length = 2;
+ record->data[0] = address >> 24;
+ record->data[1] = address >> 16;
+ ao_hex_record_set_checksum(record);
+
+ hex_file->records[nrecord++] = record;
+
+ record = calloc(sizeof (struct ao_hex_record) + length, 1);
+ record->type = AO_HEX_RECORD_SYMBOL;
+ record->address = address;
+ record->length = length;
+ memcpy(record->data, name, length);
+ ao_hex_record_set_checksum(record);
+
+ hex_file->records[nrecord++] = record;
+ }
+
+ hex_file->nrecord = nrecord;
+ return hex_file;
+}
+
+static bool
+ao_hex_write_record(FILE *file, struct ao_hex_record *record)
+{
+ int i;
+
+ fputc(':', file);
+ fprintf(file, "%02x", record->length);
+ fprintf(file, "%04x", record->address);
+ fprintf(file, "%02x", record->type);
+ for (i = 0; i < record->length; i++)
+ fprintf(file, "%02x", record->data[i]);
+ fprintf(file, "%02x", record->checksum);
+ fputc('\n', file);
+ return true;
+}
+
+bool
+ao_hex_save(FILE *file, struct ao_hex_image *image,
+ struct ao_sym *symbols, int num_symbols)
+{
+ struct ao_hex_file *hex_file;
+ int i;
+ bool ret = false;
+
+ hex_file = ao_hex_file_create(image, symbols, num_symbols);
+ if (!hex_file)
+ goto create_failed;
+
+ for (i = 0; i < hex_file->nrecord; i++) {
+ if (!ao_hex_write_record(file, hex_file->records[i]))
+ goto write_failed;
+ }
+ ret = true;
+
+ if (fflush(file) != 0)
+ ret = false;
+write_failed:
+ ao_hex_file_free(hex_file);
+create_failed:
+ return ret;
+}
diff --git a/ao-tools/lib/ao-hex.h b/ao-tools/lib/ao-hex.h
index 8528eb45..98497460 100644
--- a/ao-tools/lib/ao-hex.h
+++ b/ao-tools/lib/ao-hex.h
@@ -19,6 +19,8 @@
#define _AO_HEX_H_
#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
#define AO_HEX_RECORD_NORMAL 0x00
#define AO_HEX_RECORD_EOF 0x01
@@ -47,6 +49,14 @@ struct ao_hex_image {
uint8_t data[0];
};
+struct ao_sym {
+ unsigned addr;
+ unsigned default_addr;
+ char *name;
+ bool required;
+ bool found;
+};
+
struct ao_hex_file *
ao_hex_file_read(FILE *file, char *name);
@@ -60,9 +70,13 @@ void
ao_hex_image_free(struct ao_hex_image *image);
struct ao_hex_image *
-ao_hex_load(char *filename);
+ao_hex_load(char *filename, struct ao_sym **symbols, int *num_symbols);
int
ao_hex_image_equal(struct ao_hex_image *a, struct ao_hex_image *b);
+bool
+ao_hex_save(FILE *file, struct ao_hex_image *image,
+ struct ao_sym *symbols, int num_symbols);
+
#endif /* _AO_HEX_H_ */