util: postprocess: remove support for elf, restructure relocation code
Change-Id: Ie6b4b52c3e26ca6abc2d5067b5f97290c50f7105
Signed-off-by: Alexey Polyudov <apolyudov@google.com>
(cherry picked from commit d489d84b219a2b635d30bd4314f6698fbffe98a8)
diff --git a/util/nanoapp_postprocess/Android.mk b/util/nanoapp_postprocess/Android.mk
index 89a62a3..b20deec 100644
--- a/util/nanoapp_postprocess/Android.mk
+++ b/util/nanoapp_postprocess/Android.mk
@@ -33,13 +33,6 @@
LOCAL_MODULE := nanoapp_postprocess
-# libelf needed for ELF parsing support, libz required by libelf
-LOCAL_STATIC_LIBRARIES := libelf libz
-
-# Statically linking libc++ so this binary can be copied out of the tree and
-# still work (needed by dependencies)
-LOCAL_CXX_STL := libc++_static
-
LOCAL_MODULE_TAGS := optional
include $(BUILD_HOST_EXECUTABLE)
diff --git a/util/nanoapp_postprocess/Makefile b/util/nanoapp_postprocess/Makefile
index 9b05916..469e686 100644
--- a/util/nanoapp_postprocess/Makefile
+++ b/util/nanoapp_postprocess/Makefile
@@ -20,7 +20,7 @@
CC_FLAGS = -Wall -Wextra -Werror -I../../lib/include --std=c99
$(APP): $(SRC) Makefile
- $(CC) $(CC_FLAGS) -o $(APP) -O2 $(SRC) -lelf
+ $(CC) $(CC_FLAGS) -o $(APP) -O2 $(SRC)
clean:
rm -f $(APP)
\ No newline at end of file
diff --git a/util/nanoapp_postprocess/postprocess.c b/util/nanoapp_postprocess/postprocess.c
index 739454c..e498419 100644
--- a/util/nanoapp_postprocess/postprocess.c
+++ b/util/nanoapp_postprocess/postprocess.c
@@ -16,8 +16,6 @@
#include <assert.h>
#include <fcntl.h>
-#include <gelf.h>
-#include <libelf.h>
#include <sys/types.h>
#include <stdbool.h>
#include <unistd.h>
@@ -72,115 +70,128 @@
uint8_t type;
};
+struct NanoAppInfo {
+ union {
+ struct BinHdr *bin;
+ uint8_t *data;
+ };
+ size_t dataSizeUsed;
+ size_t dataSizeAllocated;
+ size_t codeAndDataSize; // not including symbols, relocs and BinHdr
+ size_t codeAndRoDataSize; // also not including GOT & RW data in flash
+ struct SymtabEntry *symtab;
+ size_t symtabSize; // number of symbols
+ struct RelocEntry *reloc;
+ size_t relocSize; // number of reloc entries
+ struct NanoRelocEntry *nanoReloc;
+ size_t nanoRelocSize; // number of nanoReloc entries <= relocSize
+ uint8_t *packedNanoReloc;
+ size_t packedNanoRelocSize;
+
+ bool debug;
+};
+
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(ary) (sizeof(ary) / sizeof((ary)[0]))
#endif
-#define DBG(fmt, ...) printf(fmt "\n", ##__VA_ARGS__)
+static FILE *stdlog = NULL;
+
+#define DBG(fmt, ...) fprintf(stdlog, fmt "\n", ##__VA_ARGS__)
#define ERR(fmt, ...) fprintf(stderr, fmt "\n", ##__VA_ARGS__)
-// Prints the given message followed by the most recent libelf error
-#define ELF_ERR(fmt, ...) ERR(fmt ": %s\n", ##__VA_ARGS__, elf_errmsg(-1))
-
-struct ElfAppSection {
- void *data;
- size_t size;
-};
-
-struct ElfNanoApp {
- struct ElfAppSection flash;
- struct ElfAppSection data;
- struct ElfAppSection relocs;
- struct ElfAppSection symtab;
-
- // Not parsed from file, but constructed via genElfNanoRelocs
- struct ElfAppSection packedNanoRelocs;
-};
-
static void fatalUsage(const char *name, const char *msg, const char *arg)
{
if (msg && arg)
- fprintf(stderr, "Error: %s: %s\n\n", msg, arg);
+ ERR("Error: %s: %s\n", msg, arg);
else if (msg)
- fprintf(stderr, "Error: %s\n\n", msg);
+ ERR("Error: %s\n", msg);
- fprintf(stderr, "USAGE: %s [-v] [-k <key id>] [-a <app id>] [-r] [-n <layout name>] [-i <layout id>] <input file> [<output file>]\n"
- " -v : be verbose\n"
- " -n <layout name> : app, os, key\n"
- " -i <layout id> : 1 (app), 2 (key), 3 (os)\n"
- " -f <layout flags>: 16-bit hex value, stored as layout-specific flags\n"
- " -a <app ID> : 64-bit hex number != 0\n"
- " -k <key ID> : 64-bit hex number != 0\n"
- " -r : bare (no AOSP header); used only for inner OS image generation\n"
- " -s : treat input as statically linked ELF (app layout only)\n"
- " layout ID and layout name control the same parameter, so only one of them needs to be used\n"
- , name);
+ ERR("USAGE: %s [-v] [-k <key id>] [-a <app id>] [-r] [-n <layout name>] [-i <layout id>] <input file> [<output file>]\n"
+ " -v : be verbose\n"
+ " -n <layout name> : app, os, key\n"
+ " -i <layout id> : 1 (app), 2 (key), 3 (os)\n"
+ " -f <layout flags>: 16-bit hex value, stored as layout-specific flags\n"
+ " -a <app ID> : 64-bit hex number != 0\n"
+ " -k <key ID> : 64-bit hex number != 0\n"
+ " -r : bare (no AOSP header); used only for inner OS image generation\n"
+ " layout ID and layout name control the same parameter, so only one of them needs to be used\n"
+ , name);
exit(1);
}
-static uint8_t *packNanoRelocs(struct NanoRelocEntry *nanoRelocs, uint32_t outNumRelocs, uint32_t *finalPackedNanoRelocSz, bool verbose)
+bool packNanoRelocs(struct NanoAppInfo *app)
{
- uint32_t i, j, k;
+ size_t i, j, k;
uint8_t *packedNanoRelocs;
uint32_t packedNanoRelocSz;
uint32_t lastOutType = 0, origin = 0;
+ bool verbose = app->debug;
//sort by type and then offset
- for (i = 0; i < outNumRelocs; i++) {
+ for (i = 0; i < app->nanoRelocSize; i++) {
struct NanoRelocEntry t;
- for (k = i, j = k + 1; j < outNumRelocs; j++) {
- if (nanoRelocs[j].type > nanoRelocs[k].type)
+ for (k = i, j = k + 1; j < app->nanoRelocSize; j++) {
+ if (app->nanoReloc[j].type > app->nanoReloc[k].type)
continue;
- if ((nanoRelocs[j].type < nanoRelocs[k].type) || (nanoRelocs[j].ofstInRam < nanoRelocs[k].ofstInRam))
+ if ((app->nanoReloc[j].type < app->nanoReloc[k].type) || (app->nanoReloc[j].ofstInRam < app->nanoReloc[k].ofstInRam))
k = j;
}
- memcpy(&t, nanoRelocs + i, sizeof(struct NanoRelocEntry));
- memcpy(nanoRelocs + i, nanoRelocs + k, sizeof(struct NanoRelocEntry));
- memcpy(nanoRelocs + k, &t, sizeof(struct NanoRelocEntry));
+ memcpy(&t, app->nanoReloc + i, sizeof(struct NanoRelocEntry));
+ memcpy(app->nanoReloc + i, app->nanoReloc + k, sizeof(struct NanoRelocEntry));
+ memcpy(app->nanoReloc + k, &t, sizeof(struct NanoRelocEntry));
- if (verbose)
- fprintf(stderr, "SortedReloc[%3" PRIu32 "] = {0x%08" PRIX32 ",0x%02" PRIX8 "}\n", i, nanoRelocs[i].ofstInRam, nanoRelocs[i].type);
+ if (app->debug)
+ DBG("SortedReloc[%3zu] = {0x%08" PRIX32 ",0x%02" PRIX8 "}", i, app->nanoReloc[i].ofstInRam, app->nanoReloc[i].type);
}
//produce output nanorelocs in packed format
- packedNanoRelocs = malloc(outNumRelocs * 6); //definitely big enough
+ packedNanoRelocs = malloc(app->nanoRelocSize * 6); //definitely big enough
packedNanoRelocSz = 0;
- for (i = 0; i < outNumRelocs; i++) {
+
+ if (!packedNanoRelocs) {
+ ERR("Failed to allocate memory for packed relocs");
+ return false;
+ }
+
+ for (i = 0; i < app->nanoRelocSize; i++) {
uint32_t displacement;
- if (lastOutType != nanoRelocs[i].type) { //output type if ti changed
- if (nanoRelocs[i].type - lastOutType == 1) {
+ if (lastOutType != app->nanoReloc[i].type) { //output type if ti changed
+ if (app->nanoReloc[i].type - lastOutType == 1) {
packedNanoRelocs[packedNanoRelocSz++] = TOKEN_RELOC_TYPE_NEXT;
if (verbose)
- fprintf(stderr, "Out: RelocTC (1) // to 0x%02" PRIX8 "\n", nanoRelocs[i].type);
- }
- else {
+ DBG("Out: RelocTC [size 1] // to 0x%02" PRIX8, app->nanoReloc[i].type);
+ } else {
packedNanoRelocs[packedNanoRelocSz++] = TOKEN_RELOC_TYPE_CHG;
- packedNanoRelocs[packedNanoRelocSz++] = nanoRelocs[i].type - lastOutType - 1;
+ packedNanoRelocs[packedNanoRelocSz++] = app->nanoReloc[i].type - lastOutType - 1;
if (verbose)
- fprintf(stderr, "Out: RelocTC (0x%02" PRIX8 ") // to 0x%02" PRIX8 "\n", (uint8_t)(nanoRelocs[i].type - lastOutType - 1), nanoRelocs[i].type);
+ DBG("Out: RelocTC [size 2] (0x%02" PRIX8 ") // to 0x%02" PRIX8,
+ (uint8_t)(app->nanoReloc[i].type - lastOutType - 1), app->nanoReloc[i].type);
}
- lastOutType = nanoRelocs[i].type;
+ lastOutType = app->nanoReloc[i].type;
origin = 0;
}
- displacement = nanoRelocs[i].ofstInRam - origin;
- origin = nanoRelocs[i].ofstInRam + 4;
+ displacement = app->nanoReloc[i].ofstInRam - origin;
+ origin = app->nanoReloc[i].ofstInRam + 4;
if (displacement & 3) {
- fprintf(stderr, "Unaligned relocs are not possible!\n");
- exit(-5);
+ ERR("Unaligned relocs are not possible!");
+ return false;
}
displacement /= 4;
//might be start of a run. look into that
if (!displacement) {
- for (j = 1; j + i < outNumRelocs && j < MAX_RUN_LEN && nanoRelocs[j + i].type == lastOutType && nanoRelocs[j + i].ofstInRam - nanoRelocs[j + i - 1].ofstInRam == 4; j++);
+ for (j = 1; (j + i) < app->nanoRelocSize && j < MAX_RUN_LEN &&
+ app->nanoReloc[j + i].type == lastOutType &&
+ (app->nanoReloc[j + i].ofstInRam - app->nanoReloc[j + i - 1].ofstInRam) == 4; j++);
if (j >= MIN_RUN_LEN) {
if (verbose)
- fprintf(stderr, "Out: Reloc0 x%" PRIX32 "\n", j);
+ DBG("Out: Reloc0 [size 2]; repeat=%zu", j);
packedNanoRelocs[packedNanoRelocSz++] = TOKEN_CONSECUTIVE;
packedNanoRelocs[packedNanoRelocSz++] = j - MIN_RUN_LEN;
- origin = nanoRelocs[j + i - 1].ofstInRam + 4; //reset origin to last one
+ origin = app->nanoReloc[j + i - 1].ofstInRam + 4; //reset origin to last one
i += j - 1; //loop will increment anyways, hence +1
continue;
}
@@ -189,29 +200,26 @@
//produce output
if (displacement <= MAX_8_BIT_NUM) {
if (verbose)
- fprintf(stderr, "Out: Reloc8 0x%02" PRIX32 "\n", displacement);
+ DBG("Out: Reloc8 [size 1] 0x%02" PRIX32, displacement);
packedNanoRelocs[packedNanoRelocSz++] = displacement;
- }
- else if (displacement <= MAX_16_BIT_NUM) {
+ } else if (displacement <= MAX_16_BIT_NUM) {
if (verbose)
- fprintf(stderr, "Out: Reloc16 0x%06" PRIX32 "\n", displacement);
+ DBG("Out: Reloc16 [size 3] 0x%06" PRIX32, displacement);
displacement -= MAX_8_BIT_NUM;
packedNanoRelocs[packedNanoRelocSz++] = TOKEN_16BIT_OFST;
packedNanoRelocs[packedNanoRelocSz++] = displacement;
packedNanoRelocs[packedNanoRelocSz++] = displacement >> 8;
- }
- else if (displacement <= MAX_24_BIT_NUM) {
+ } else if (displacement <= MAX_24_BIT_NUM) {
if (verbose)
- fprintf(stderr, "Out: Reloc24 0x%08" PRIX32 "\n", displacement);
+ DBG("Out: Reloc24 [size 4] 0x%08" PRIX32, displacement);
displacement -= MAX_16_BIT_NUM;
packedNanoRelocs[packedNanoRelocSz++] = TOKEN_24BIT_OFST;
packedNanoRelocs[packedNanoRelocSz++] = displacement;
packedNanoRelocs[packedNanoRelocSz++] = displacement >> 8;
packedNanoRelocs[packedNanoRelocSz++] = displacement >> 16;
- }
- else {
+ } else {
if (verbose)
- fprintf(stderr, "Out: Reloc32 0x%08" PRIX32 "\n", displacement);
+ DBG("Out: Reloc32 [size 5] 0x%08" PRIX32, displacement);
packedNanoRelocs[packedNanoRelocSz++] = TOKEN_32BIT_OFST;
packedNanoRelocs[packedNanoRelocSz++] = displacement;
packedNanoRelocs[packedNanoRelocSz++] = displacement >> 8;
@@ -220,16 +228,18 @@
}
}
- *finalPackedNanoRelocSz = packedNanoRelocSz;
- return packedNanoRelocs;
+ app->packedNanoReloc = packedNanoRelocs;
+ app->packedNanoRelocSize = packedNanoRelocSz;
+
+ return true;
}
-static int finalizeAndWrite(uint8_t *buf, uint32_t bufUsed, uint32_t bufSz, FILE *out, uint32_t layoutFlags, uint64_t appId)
+static int finalizeAndWrite(struct NanoAppInfo *inf, FILE *out, uint32_t layoutFlags, uint64_t appId)
{
- int ret;
+ bool good = true;
struct AppInfo app;
struct SectInfo *sect;
- struct BinHdr *bin = (struct BinHdr *) buf;
+ struct BinHdr *bin = inf->bin;
struct ImageHeader outHeader = {
.aosp = (struct nano_app_binary_t) {
.header_version = 1,
@@ -245,58 +255,159 @@
.flags = layoutFlags,
},
};
- uint32_t dataOffset = sizeof(outHeader) + sizeof(app);
- uint32_t hdrDiff = dataOffset - sizeof(*bin);
+
app.sect = bin->sect;
app.vec = bin->vec;
-
- assertMem(bufUsed + hdrDiff, bufSz);
-
- memmove(buf + dataOffset, buf + sizeof(*bin), bufUsed - sizeof(*bin));
- bufUsed += hdrDiff;
- memcpy(buf, &outHeader, sizeof(outHeader));
- memcpy(buf + sizeof(outHeader), &app, sizeof(app));
sect = &app.sect;
//if we have any bytes to output, show stats
- if (bufUsed) {
- uint32_t codeAndRoDataSz = sect->data_data;
- uint32_t relocsSz = sect->rel_end - sect->rel_start;
- uint32_t gotSz = sect->got_end - sect->data_start;
- uint32_t bssSz = sect->bss_end - sect->bss_start;
+ if (inf->codeAndRoDataSize) {
+ size_t binarySize = 0;
+ size_t gotSz = sect->got_end - sect->data_start;
+ size_t bssSz = sect->bss_end - sect->bss_start;
- fprintf(stderr,"Final binary size %" PRIu32 " bytes\n", bufUsed);
- fprintf(stderr, "\n");
- fprintf(stderr, " FW header size (flash): %6zu bytes\n", FLASH_RELOC_OFFSET);
- fprintf(stderr, " Code + RO data (flash): %6" PRIu32 " bytes\n", codeAndRoDataSz);
- fprintf(stderr, " Relocs (flash): %6" PRIu32 " bytes\n", relocsSz);
- fprintf(stderr, " GOT + RW data (flash & RAM): %6" PRIu32 " bytes\n", gotSz);
- fprintf(stderr, " BSS (RAM): %6" PRIu32 " bytes\n", bssSz);
- fprintf(stderr, "\n");
- fprintf(stderr,"Runtime flash use: %" PRIu32 " bytes\n", (uint32_t)(codeAndRoDataSz + relocsSz + gotSz + FLASH_RELOC_OFFSET));
- fprintf(stderr,"Runtime RAM use: %" PRIu32 " bytes\n", gotSz + bssSz);
+ good = fwrite(&outHeader, sizeof(outHeader), 1, out) == 1 && good;
+ binarySize += sizeof(outHeader);
+
+ good = fwrite(&app, sizeof(app), 1, out) == 1 && good;
+ binarySize += sizeof(app);
+
+ good = fwrite(&bin[1], inf->codeAndDataSize, 1, out) == 1 && good;
+ binarySize += inf->codeAndDataSize;
+
+ if (inf->packedNanoReloc && inf->packedNanoRelocSize) {
+ good = fwrite(inf->packedNanoReloc, inf->packedNanoRelocSize, 1, out) == 1 && good;
+ binarySize += inf->packedNanoRelocSize;
+ }
+
+ if (!good) {
+ ERR("Failed to write output file: %s\n", strerror(errno));
+ } else {
+ DBG("Final binary size %zu bytes", binarySize);
+ DBG("");
+ DBG(" FW header size (flash): %6zu bytes", FLASH_RELOC_OFFSET);
+ DBG(" Code + RO data (flash): %6zu bytes", inf->codeAndRoDataSize);
+ DBG(" Relocs (flash): %6zu bytes", inf->packedNanoRelocSize);
+ DBG(" GOT + RW data (flash & RAM): %6zu bytes", gotSz);
+ DBG(" BSS (RAM): %6zu bytes", bssSz);
+ DBG("");
+ DBG("Runtime flash use: %zu bytes",
+ (size_t)(inf->codeAndRoDataSize + inf->packedNanoRelocSize + gotSz + FLASH_RELOC_OFFSET));
+ DBG("Runtime RAM use: %zu bytes", gotSz + bssSz);
+ }
}
- ret = fwrite(buf, bufUsed, 1, out) == 1 ? 0 : 2;
- if (ret)
- fprintf(stderr, "Failed to write output file: %s\n", strerror(errno));
+ return good ? 0 : 2;
+}
- return ret;
+// Subtracts the fixed memory region offset from an absolute address and returns
+// the associated NANO_RELOC_* value, or NANO_RELOC_LAST if the address is not
+// in the expected range.
+static uint8_t fixupAddress(uint32_t *addr, struct SymtabEntry *sym, bool debug)
+{
+ uint8_t type;
+ uint32_t old = *addr;
+
+ (*addr) += sym->addr;
+ // TODO: this assumes that the host running this tool has the same
+ // endianness as the image file/target processor
+ if (IS_IN_RAM(*addr)) {
+ *addr -= RAM_BASE;
+ type = NANO_RELOC_TYPE_RAM;
+ if (debug)
+ DBG("Fixup addr 0x%08" PRIX32 " (RAM) --> 0x%08" PRIX32, old, *addr);
+ } else if (IS_IN_FLASH(*addr)) {
+ *addr -= FLASH_BASE + BINARY_RELOC_OFFSET;
+ type = NANO_RELOC_TYPE_FLASH;
+ if (debug)
+ DBG("Fixup addr 0x%08" PRIX32 " (FLASH) --> 0x%08" PRIX32, old, *addr);
+ } else {
+ ERR("Error: invalid address 0x%08" PRIX32, *addr);
+ type = NANO_RELOC_LAST;
+ }
+
+ return type;
+}
+
+static void relocDiag(const struct NanoAppInfo *app, const struct RelocEntry *reloc, const char *msg)
+{
+ size_t symIdx = reloc->info >> 8;
+ uint8_t symType = reloc->info;
+
+ ERR("Reloc %zu %s", reloc - app->reloc, msg);
+ ERR("INFO:");
+ ERR(" Where: 0x%08" PRIX32, reloc->where);
+ ERR(" type: %" PRIu8, symType);
+ ERR(" sym: %zu", symIdx);
+ if (symIdx < app->symtabSize) {
+ struct SymtabEntry *sym = &app->symtab[symIdx];
+ ERR(" addr: %" PRIu32, sym->addr);
+ } else {
+ ERR(" addr: <invalid>");
+ }
+}
+
+static uint8_t fixupReloc(struct NanoAppInfo *app, struct RelocEntry *reloc,
+ struct SymtabEntry *sym, struct NanoRelocEntry *nanoReloc)
+{
+ uint8_t type;
+ uint32_t *addr;
+ uint32_t relocOffset = reloc->where;
+ uint32_t flashDataOffset = 0;
+
+ if (IS_IN_FLASH(relocOffset)) {
+ relocOffset -= FLASH_BASE;
+ flashDataOffset = 0;
+ } else if (IS_IN_RAM(reloc->where)) {
+ relocOffset = reloc->where - RAM_BASE;
+ flashDataOffset = app->bin->sect.data_data - FLASH_BASE;
+ } else {
+ relocDiag(app, reloc, "is neither in RAM nor in FLASH");
+ return NANO_RELOC_LAST;
+ }
+
+ addr = (uint32_t*)(app->data + flashDataOffset + relocOffset);
+
+ if (flashDataOffset + relocOffset >= app->dataSizeUsed - sizeof(*addr)) {
+ relocDiag(app, reloc, "points outside valid data area");
+ return NANO_RELOC_LAST;
+ }
+
+ switch (reloc->info & 0xFF) {
+ case RELOC_TYPE_ABS_S:
+ case RELOC_TYPE_ABS_D:
+ type = fixupAddress(addr, sym, app->debug);
+ break;
+
+ case RELOC_TYPE_SECT:
+ if (sym->addr) {
+ relocDiag(app, reloc, "has section relocation with non-zero symbol address");
+ return NANO_RELOC_LAST;
+ }
+ type = fixupAddress(addr, sym, app->debug);
+ break;
+ default:
+ relocDiag(app, reloc, "has unknown type");
+ type = NANO_RELOC_LAST;
+ }
+
+ if (nanoReloc && type != NANO_RELOC_LAST) {
+ nanoReloc->ofstInRam = relocOffset;
+ nanoReloc->type = type;
+ }
+
+ return type;
}
static int handleApp(uint8_t **pbuf, uint32_t bufUsed, FILE *out, uint32_t layoutFlags, uint64_t appId, bool verbose)
{
- uint32_t i, numRelocs, numSyms, outNumRelocs = 0, packedNanoRelocSz;
- struct NanoRelocEntry *nanoRelocs = NULL;
- struct RelocEntry *relocs;
- struct SymtabEntry *syms;
- uint8_t *packedNanoRelocs;
- uint32_t t;
+ uint32_t i;
struct BinHdr *bin;
int ret = -1;
struct SectInfo *sect;
uint8_t *buf = *pbuf;
uint32_t bufSz = bufUsed * 3 /2;
+ struct NanoAppInfo app;
//make buffer 50% bigger than bufUsed in case relocs grow out of hand
buf = reallocOrDie(buf, bufSz);
@@ -305,212 +416,139 @@
//sanity checks
bin = (struct BinHdr*)buf;
if (bufUsed < sizeof(*bin)) {
- fprintf(stderr, "File size too small\n");
+ ERR("File size too small: %" PRIu32, bufUsed);
goto out;
}
if (bin->hdr.magic != NANOAPP_FW_MAGIC) {
- fprintf(stderr, "Magic value is wrong: found %08" PRIX32
- "; expected %08" PRIX32 "\n",
- bin->hdr.magic, NANOAPP_FW_MAGIC);
+ ERR("Magic value is wrong: found %08" PRIX32"; expected %08" PRIX32, bin->hdr.magic, NANOAPP_FW_MAGIC);
goto out;
}
sect = &bin->sect;
- //do some math
- relocs = (struct RelocEntry*)(buf + sect->rel_start - FLASH_BASE);
- syms = (struct SymtabEntry*)(buf + sect->rel_end - FLASH_BASE);
- numRelocs = (sect->rel_end - sect->rel_start) / sizeof(struct RelocEntry);
- numSyms = (bufUsed + FLASH_BASE - sect->rel_end) / sizeof(struct SymtabEntry);
-
- //sanity
- if (numRelocs * sizeof(struct RelocEntry) + sect->rel_start != sect->rel_end) {
- fprintf(stderr, "Relocs of nonstandard size\n");
+ if (!IS_IN_FLASH(sect->rel_start) || !IS_IN_FLASH(sect->rel_end) || !IS_IN_FLASH(sect->data_data)) {
+ ERR("relocation data or initialized data is not in FLASH");
goto out;
}
- if (numSyms * sizeof(struct SymtabEntry) + sect->rel_end != bufUsed + FLASH_BASE) {
- fprintf(stderr, "Syms of nonstandard size\n");
+ if (!IS_IN_RAM(sect->data_start) || !IS_IN_RAM(sect->data_end) || !IS_IN_RAM(sect->bss_start) ||
+ !IS_IN_RAM(sect->bss_end) || !IS_IN_RAM(sect->got_start) || !IS_IN_RAM(sect->got_end)) {
+ ERR("data, bss, or got not in ram\n");
+ goto out;
+ }
+
+ //do some math
+ app.reloc = (struct RelocEntry*)(buf + sect->rel_start - FLASH_BASE);
+ app.symtab = (struct SymtabEntry*)(buf + sect->rel_end - FLASH_BASE);
+ app.relocSize = (sect->rel_end - sect->rel_start) / sizeof(struct RelocEntry);
+ app.nanoRelocSize = 0;
+ app.symtabSize = (struct SymtabEntry*)(buf + bufUsed) - app.symtab;
+ app.data = buf;
+ app.dataSizeAllocated = bufSz;
+ app.dataSizeUsed = bufUsed;
+ app.codeAndRoDataSize = sect->data_data - FLASH_BASE - sizeof(*bin);
+ app.codeAndDataSize = sect->rel_start - FLASH_BASE - sizeof(*bin);
+ app.debug = verbose;
+ app.nanoReloc = NULL;
+ app.packedNanoReloc = NULL;
+
+ //sanity
+ if (app.relocSize * sizeof(struct RelocEntry) + sect->rel_start != sect->rel_end) {
+ ERR("Relocs of nonstandard size");
+ goto out;
+ }
+ if (app.symtabSize * sizeof(struct SymtabEntry) + sect->rel_end != bufUsed + FLASH_BASE) {
+ ERR("Syms of nonstandard size");
goto out;
}
//show some info
- fprintf(stderr, "\nRead %" PRIu32 " bytes of binary.\n", bufUsed);
if (verbose)
- fprintf(stderr, "Found %" PRIu32 " relocs and a %" PRIu32 "-entry symbol table\n", numRelocs, numSyms);
+ DBG("Found %zu relocs and a %zu-entry symbol table", app.relocSize, app.symtabSize);
//handle relocs
- nanoRelocs = malloc(sizeof(struct NanoRelocEntry[numRelocs]));
- if (!nanoRelocs) {
- fprintf(stderr, "Failed to allocate a nano-reloc table\n");
+ app.nanoReloc = malloc(sizeof(struct NanoRelocEntry[app.relocSize]));
+ if (!app.nanoReloc) {
+ ERR("Failed to allocate a nano-reloc table\n");
goto out;
}
- for (i = 0; i < numRelocs; i++) {
- uint32_t relocType = relocs[i].info & 0xff;
- uint32_t whichSym = relocs[i].info >> 8;
- uint32_t *valThereP;
+ for (i = 0; i < app.relocSize; i++) {
+ struct RelocEntry *reloc = &app.reloc[i];
+ struct NanoRelocEntry *nanoReloc = &app.nanoReloc[app.nanoRelocSize];
+ uint32_t relocType = reloc->info & 0xff;
+ uint32_t whichSym = reloc->info >> 8;
+ struct SymtabEntry *sym = &app.symtab[whichSym];
- if (whichSym >= numSyms) {
- fprintf(stderr, "Reloc %" PRIu32 " references a nonexistent symbol!\n"
- "INFO:\n"
- " Where: 0x%08" PRIX32 "\n"
- " type: %" PRIu32 "\n"
- " sym: %" PRIu32 "\n",
- i, relocs[i].where, relocs[i].info & 0xff, whichSym);
+ if (whichSym >= app.symtabSize) {
+ relocDiag(&app, reloc, "references a nonexistent symbol");
goto out;
}
if (verbose) {
const char *seg;
- fprintf(stderr, "Reloc[%3" PRIu32 "]:\n {@0x%08" PRIX32 ", type %3" PRIu32 ", -> sym[%3" PRIu32 "]: {@0x%08" PRIX32 "}, ",
- i, relocs[i].where, relocs[i].info & 0xff, whichSym, syms[whichSym].addr);
-
- if (IS_IN_RANGE_E(relocs[i].where, sect->bss_start, sect->bss_end))
+ if (IS_IN_RANGE_E(reloc->where, sect->bss_start, sect->bss_end))
seg = ".bss";
- else if (IS_IN_RANGE_E(relocs[i].where, sect->data_start, sect->data_end))
+ else if (IS_IN_RANGE_E(reloc->where, sect->data_start, sect->data_end))
seg = ".data";
- else if (IS_IN_RANGE_E(relocs[i].where, sect->got_start, sect->got_end))
+ else if (IS_IN_RANGE_E(reloc->where, sect->got_start, sect->got_end))
seg = ".got";
- else if (IS_IN_RANGE_E(relocs[i].where, FLASH_BASE, FLASH_BASE + sizeof(struct BinHdr)))
+ else if (IS_IN_RANGE_E(reloc->where, FLASH_BASE, FLASH_BASE + sizeof(struct BinHdr)))
seg = "APPHDR";
else
seg = "???";
- fprintf(stderr, "in %s}\n", seg);
+ DBG("Reloc[%3" PRIu32 "]:\n {@0x%08" PRIX32 ", type %3" PRIu32 ", -> sym[%3" PRIu32 "]: {@0x%08" PRIX32 "}, in %s}",
+ i, reloc->where, reloc->info & 0xff, whichSym, sym->addr, seg);
}
/* handle relocs inside the header */
- if (IS_IN_FLASH(relocs[i].where) && relocs[i].where - FLASH_BASE < sizeof(struct BinHdr) && relocType == RELOC_TYPE_SECT) {
+ if (IS_IN_FLASH(reloc->where) && reloc->where - FLASH_BASE < sizeof(struct BinHdr) && relocType == RELOC_TYPE_SECT) {
/* relocs in header are special - runtime corrects for them */
- if (syms[whichSym].addr) {
- fprintf(stderr, "Weird in-header sect reloc %" PRIu32 " to symbol %" PRIu32 " with nonzero addr 0x%08" PRIX32 "\n",
- i, whichSym, syms[whichSym].addr);
- goto out;
- }
-
- valThereP = (uint32_t*)(buf + relocs[i].where - FLASH_BASE);
- if (!IS_IN_FLASH(*valThereP)) {
- fprintf(stderr, "In-header reloc %" PRIu32 " of location 0x%08" PRIX32 " is outside of FLASH!\n"
- "INFO:\n"
- " type: %" PRIu32 "\n"
- " sym: %" PRIu32 "\n"
- " Sym Addr: 0x%08" PRIX32 "\n",
- i, relocs[i].where, relocType, whichSym, syms[whichSym].addr);
- goto out;
- }
-
- // binary header generated by objcopy, .napp header and final FW header in flash are of different size.
+ // binary header generated by objcopy, .napp header and final FW header in flash are of different layout and size.
// we subtract binary header offset here, so all the entry points are relative to beginning of "sect".
// FW will use § as a base to call these vectors; no more problems with different header sizes;
// Assumption: offsets between sect & vec, vec & code are the same in all images (or, in a simpler words, { sect, vec, code }
// must go together). this is enforced by linker script, and maintained by all tools and FW download code in the OS.
- *valThereP -= FLASH_BASE + BINARY_RELOC_OFFSET;
+
+ switch (fixupReloc(&app, reloc, sym, NULL)) {
+ case NANO_RELOC_TYPE_RAM:
+ relocDiag(&app, reloc, "is in APPHDR but relocated to RAM");
+ goto out;
+ case NANO_RELOC_TYPE_FLASH:
+ break;
+ default:
+ // other error happened; it is already reported
+ goto out;
+ }
if (verbose)
- fprintf(stderr, " -> Nano reloc skipped for in-header reloc\n");
+ DBG(" -> Nano reloc skipped for in-header reloc");
continue; /* do not produce an output reloc */
}
- if (!IS_IN_RAM(relocs[i].where)) {
- fprintf(stderr, "In-header reloc %" PRIu32 " of location 0x%08" PRIX32 " is outside of RAM!\n"
- "INFO:\n"
- " type: %" PRIu32 "\n"
- " sym: %" PRIu32 "\n"
- " Sym Addr: 0x%08" PRIX32 "\n",
- i, relocs[i].where, relocType, whichSym, syms[whichSym].addr);
+ // any other relocs may only happen in RAM
+ if (!IS_IN_RAM(reloc->where)) {
+ relocDiag(&app, reloc, "is not in RAM");
goto out;
}
- valThereP = (uint32_t*)(buf + relocs[i].where + sect->data_data - RAM_BASE - FLASH_BASE);
-
- nanoRelocs[outNumRelocs].ofstInRam = relocs[i].where - RAM_BASE;
-
- switch (relocType) {
- case RELOC_TYPE_ABS_S:
- case RELOC_TYPE_ABS_D:
- t = *valThereP;
-
- (*valThereP) += syms[whichSym].addr;
-
- if (IS_IN_FLASH(syms[whichSym].addr)) {
- (*valThereP) -= FLASH_BASE + BINARY_RELOC_OFFSET;
- nanoRelocs[outNumRelocs].type = NANO_RELOC_TYPE_FLASH;
- }
- else if (IS_IN_RAM(syms[whichSym].addr)) {
- (*valThereP) -= RAM_BASE;
- nanoRelocs[outNumRelocs].type = NANO_RELOC_TYPE_RAM;
- }
- else {
- fprintf(stderr, "Weird reloc %" PRIu32 " to symbol %" PRIu32 " in unknown memory space (addr 0x%08" PRIX32 ")\n",
- i, whichSym, syms[whichSym].addr);
- goto out;
- }
- if (verbose)
- fprintf(stderr, " -> Abs reference fixed up 0x%08" PRIX32 " -> 0x%08" PRIX32 "\n", t, *valThereP);
- break;
-
- case RELOC_TYPE_SECT:
- if (syms[whichSym].addr) {
- fprintf(stderr, "Weird sect reloc %" PRIu32 " to symbol %" PRIu32 " with nonzero addr 0x%08" PRIX32 "\n",
- i, whichSym, syms[whichSym].addr);
- goto out;
- }
-
- t = *valThereP;
-
- if (IS_IN_FLASH(*valThereP)) {
- nanoRelocs[outNumRelocs].type = NANO_RELOC_TYPE_FLASH;
- *valThereP -= FLASH_BASE + BINARY_RELOC_OFFSET;
- }
- else if (IS_IN_RAM(*valThereP)) {
- nanoRelocs[outNumRelocs].type = NANO_RELOC_TYPE_RAM;
- *valThereP -= RAM_BASE;
- }
- else {
- fprintf(stderr, "Weird sec reloc %" PRIu32 " to symbol %" PRIu32
- " in unknown memory space (addr 0x%08" PRIX32 ")\n",
- i, whichSym, *valThereP);
- goto out;
- }
- if (verbose)
- fprintf(stderr, " -> Sect reference fixed up 0x%08" PRIX32 " -> 0x%08" PRIX32 "\n", t, *valThereP);
- break;
-
- default:
- fprintf(stderr, "Weird reloc %" PRIX32 " type %" PRIX32 " to symbol %" PRIX32 "\n", i, relocType, whichSym);
- goto out;
+ if (fixupReloc(&app, reloc, sym, nanoReloc) != NANO_RELOC_LAST) {
+ app.nanoRelocSize++;
+ if (verbose)
+ DBG(" -> Nano reloc calculated as 0x%08" PRIX32 ",0x%02" PRIX8 "\n", nanoReloc->ofstInRam, nanoReloc->type);
}
-
- if (verbose)
- fprintf(stderr, " -> Nano reloc calculated as 0x%08" PRIX32 ",0x%02" PRIX8 "\n", nanoRelocs[i].ofstInRam, nanoRelocs[i].type);
- outNumRelocs++;
}
- packedNanoRelocs = packNanoRelocs(nanoRelocs, outNumRelocs, &packedNanoRelocSz, verbose);
-
- //overwrite original relocs and symtab with nanorelocs and adjust sizes
- memcpy(relocs, packedNanoRelocs, packedNanoRelocSz);
- bufUsed -= sizeof(struct RelocEntry[numRelocs]);
- bufUsed -= sizeof(struct SymtabEntry[numSyms]);
- bufUsed += packedNanoRelocSz;
- assertMem(bufUsed, bufSz);
- sect->rel_end = sect->rel_start + packedNanoRelocSz;
-
- //sanity
- if (sect->rel_end - FLASH_BASE != bufUsed) {
- fprintf(stderr, "Relocs end and file end not coincident\n");
+ if (!packNanoRelocs(&app))
goto out;
- }
+
+ // we're going to write packed relocs; set correct size
+ sect->rel_end = sect->rel_start + app.packedNanoRelocSize;
//adjust headers for easy access (RAM)
- if (!IS_IN_RAM(sect->data_start) || !IS_IN_RAM(sect->data_end) || !IS_IN_RAM(sect->bss_start) ||
- !IS_IN_RAM(sect->bss_end) || !IS_IN_RAM(sect->got_start) || !IS_IN_RAM(sect->got_end)) {
- fprintf(stderr, "data, bss, or got not in ram\n");
- goto out;
- }
sect->data_start -= RAM_BASE;
sect->data_end -= RAM_BASE;
sect->bss_start -= RAM_BASE;
@@ -519,312 +557,17 @@
sect->got_end -= RAM_BASE;
//adjust headers for easy access (FLASH)
- if (!IS_IN_FLASH(sect->data_data) || !IS_IN_FLASH(sect->rel_start) || !IS_IN_FLASH(sect->rel_end)) {
- fprintf(stderr, "data.data, or rel not in flash\n");
- goto out;
- }
sect->data_data -= FLASH_BASE + BINARY_RELOC_OFFSET;
sect->rel_start -= FLASH_BASE + BINARY_RELOC_OFFSET;
sect->rel_end -= FLASH_BASE + BINARY_RELOC_OFFSET;
- ret = finalizeAndWrite(buf, bufUsed, bufSz, out, layoutFlags, appId);
+ ret = finalizeAndWrite(&app, out, layoutFlags, appId);
out:
- free(nanoRelocs);
+ free(app.nanoReloc);
+ free(app.packedNanoReloc);
return ret;
}
-static void elfExtractSectionPointer(const Elf_Data *data, const char *name, struct ElfNanoApp *app)
-{
- // Maps section names to their byte offset in struct ElfNanoApp. Note that
- // this assumes that the linker script puts text/code in the .flash section,
- // RW data in .data, that relocs for .data are included in .rel.data, and
- // the symbol table is emitted in .symtab
- const struct SectionMap {
- const char *name;
- size_t offset;
- } sectionMap[] = {
- {
- .name = ".flash",
- .offset = offsetof(struct ElfNanoApp, flash),
- },
- {
- .name = ".data",
- .offset = offsetof(struct ElfNanoApp, data),
- },
- {
- .name = ".rel.data",
- .offset = offsetof(struct ElfNanoApp, relocs),
- },
- {
- .name = ".symtab",
- .offset = offsetof(struct ElfNanoApp, symtab),
- },
- };
- struct ElfAppSection *appSection;
- uint8_t *appBytes = (uint8_t *) app;
-
- for (size_t i = 0; i < ARRAY_SIZE(sectionMap); i++) {
- if (strcmp(name, sectionMap[i].name) != 0) {
- continue;
- }
- appSection = (struct ElfAppSection *) &appBytes[sectionMap[i].offset];
-
- appSection->data = data->d_buf;
- appSection->size = data->d_size;
-
- DBG("Found section %s with size %zu", name, appSection->size);
- break;
- }
-}
-
-// Populates a struct ElfNanoApp with data parsed from the ELF
-static bool elfParse(Elf *elf, struct ElfNanoApp *app)
-{
- size_t shdrstrndx;
- Elf_Scn *scn = NULL;
- GElf_Shdr shdr;
- char *sectionName;
- Elf_Data *elf_data;
-
- memset(app, 0, sizeof(*app));
- if (elf_getshdrstrndx(elf, &shdrstrndx) != 0) {
- ELF_ERR("Couldn't get section name string table index");
- return false;
- }
-
- while ((scn = elf_nextscn(elf, scn)) != NULL) {
- if (gelf_getshdr(scn, &shdr) != &shdr) {
- ELF_ERR("Error getting section header");
- return false;
- }
- sectionName = elf_strptr(elf, shdrstrndx, shdr.sh_name);
-
- elf_data = elf_getdata(scn, NULL);
- if (!elf_data) {
- ELF_ERR("Error getting data for section %s", sectionName);
- return false;
- }
-
- elfExtractSectionPointer(elf_data, sectionName, app);
- }
-
- return true;
-}
-
-static bool loadNanoappElfFile(const char *fileName, struct ElfNanoApp *app)
-{
- int fd;
- Elf *elf;
-
- if (elf_version(EV_CURRENT) == EV_NONE) {
- ELF_ERR("Failed to initialize ELF library");
- return false;
- }
-
- fd = open(fileName, O_RDONLY, 0);
- if (fd < 0) {
- ERR("Failed to open file %s for reading: %s", fileName, strerror(errno));
- return false;
- }
-
- elf = elf_begin(fd, ELF_C_READ, NULL);
- if (elf == NULL) {
- ELF_ERR("Failed to open ELF");
- return false;
- }
-
- if (!elfParse(elf, app)) {
- ERR("Failed to parse ELF file");
- return false;
- }
-
- return true;
-}
-
-// Subtracts the fixed memory region offset from an absolute address and returns
-// the associated NANO_RELOC_* value, or NANO_RELOC_LAST if the address is not
-// in the expected range.
-// Not strictly tied to ELF usage, but handled slightly differently.
-static uint8_t fixupAddrElf(uint32_t *addr)
-{
- uint8_t type;
-
- // TODO: this assumes that the host running this tool has the same
- // endianness as the image file/target processor
- if (IS_IN_FLASH(*addr)) {
- DBG("Fixup addr 0x%08" PRIX32 " (flash) --> 0x%08" PRIX32, *addr,
- (uint32_t) (*addr - (FLASH_BASE + BINARY_RELOC_OFFSET)));
- *addr -= FLASH_BASE + BINARY_RELOC_OFFSET;
- type = NANO_RELOC_TYPE_FLASH;
- } else if (IS_IN_RAM(*addr)) {
- DBG("Fixup addr 0x%08" PRIX32 " (ram) --> 0x%08" PRIX32, *addr,
- *addr - RAM_BASE);
- *addr -= RAM_BASE;
- type = NANO_RELOC_TYPE_RAM;
- } else {
- DBG("Error: invalid address 0x%08" PRIX32, *addr);
- type = NANO_RELOC_LAST;
- }
-
- return type;
-}
-
-// Fixup addresses in the header to be relative. Not strictly tied to the ELF
-// format, but used only in that program flow in the current implementation.
-static bool fixupHeaderElf(const struct ElfNanoApp *app)
-{
- struct BinHdr *hdr = (struct BinHdr *) app->flash.data;
-
- DBG("Appyling fixups to header");
- if (fixupAddrElf(&hdr->sect.data_start) != NANO_RELOC_TYPE_RAM ||
- fixupAddrElf(&hdr->sect.data_end) != NANO_RELOC_TYPE_RAM ||
- fixupAddrElf(&hdr->sect.bss_start) != NANO_RELOC_TYPE_RAM ||
- fixupAddrElf(&hdr->sect.bss_end) != NANO_RELOC_TYPE_RAM ||
- fixupAddrElf(&hdr->sect.got_start) != NANO_RELOC_TYPE_RAM ||
- fixupAddrElf(&hdr->sect.got_end) != NANO_RELOC_TYPE_RAM) {
- ERR(".data, .bss, or .got not in RAM address space!");
- return false;
- }
-
- if (fixupAddrElf(&hdr->sect.rel_start) != NANO_RELOC_TYPE_FLASH ||
- fixupAddrElf(&hdr->sect.rel_end) != NANO_RELOC_TYPE_FLASH ||
- fixupAddrElf(&hdr->sect.data_data) != NANO_RELOC_TYPE_FLASH) {
- ERR(".data loadaddr, or .relocs not in flash address space!");
- return false;
- }
-
- if (fixupAddrElf(&hdr->vec.init) != NANO_RELOC_TYPE_FLASH ||
- fixupAddrElf(&hdr->vec.end) != NANO_RELOC_TYPE_FLASH ||
- fixupAddrElf(&hdr->vec.handle) != NANO_RELOC_TYPE_FLASH) {
- ERR("Entry point(s) not in flash address space!");
- return false;
- }
-
- return true;
-}
-
-// Fixup addresses in .data, .init_array/.fini_array, and .got, and generates
-// packed array of nano reloc entries. The app header must have already been
-// fixed up.
-static bool genElfNanoRelocs(struct ElfNanoApp *app, bool verbose)
-{
- const struct BinHdr *hdr = (const struct BinHdr *) app->flash.data;
- const struct SectInfo *sect = &hdr->sect;
- bool success = false;
-
- size_t numDataRelocs = app->relocs.size / sizeof(Elf32_Rel);
- size_t gotCount = (sect->got_end - sect->got_start) / sizeof(uint32_t);
- size_t numInitFuncs = (sect->bss_start - sect->data_end) / sizeof(uint32_t);
-
- size_t totalRelocCount = (numDataRelocs + numInitFuncs + gotCount);
- struct NanoRelocEntry *nanoRelocs = malloc(
- totalRelocCount * sizeof(struct NanoRelocEntry));
- if (!nanoRelocs) {
- ERR("Couldn't allocate memory for nano relocs! Needed %zu bytes",
- totalRelocCount * sizeof(struct NanoRelocEntry));
- return false;
- }
-
- uint8_t *data = app->data.data;
- const Elf32_Rel *relocs = (const Elf32_Rel *) app->relocs.data;
- const Elf32_Sym *syms = (const Elf32_Sym *) app->symtab.data;
- size_t numRelocs = 0;
-
- DBG("Parsing relocs for .data (%zu):", numDataRelocs);
- for (size_t i = 0; i < numDataRelocs; i++) {
- uint32_t type = ELF32_R_TYPE(relocs[i].r_info);
- uint32_t sym = ELF32_R_SYM(relocs[i].r_info);
-
- DBG(" [%3zu] 0x%08" PRIx32 " type %2" PRIu32 " symIdx %3" PRIu32
- " --> 0x%08" PRIx32, i, relocs[i].r_offset, type, sym,
- syms[sym].st_value);
- // Note that R_ARM_TARGET1 is used for .init_array/.fini_array support,
- // and can be interpreted either as ABS32 or REL32, depending on the
- // runtime; we expect it to be ABS32.
- if (type == R_ARM_ABS32 || type == R_ARM_TARGET1) {
- if (!IS_IN_RAM(relocs[i].r_offset)) {
- ERR("Reloc for .data not in RAM address range!");
- goto out;
- }
- uint32_t offset = relocs[i].r_offset - RAM_BASE;
- uint32_t *addr = (uint32_t *) &data[offset];
-
- nanoRelocs[numRelocs].type = fixupAddrElf(addr);
- nanoRelocs[numRelocs].ofstInRam = offset;
- numRelocs++;
- } else {
- // TODO: Assuming that the ELF only contains absolute addresses in
- // the .data section; may need to handle other relocation types in
- // the future
- ERR("Error: Unexpected reloc type %" PRIu32 " at index %zu",
- type, i);
- goto out;
- }
- }
-
- DBG("Updating GOT entries (%zu):", gotCount);
- for (uint32_t offset = sect->got_start; offset < sect->got_end;
- offset += sizeof(uint32_t)) {
- uint32_t *addr = (uint32_t *) &data[offset];
- // Skip values that are set to 0, these seem to be padding (?)
- if (*addr) {
- nanoRelocs[numRelocs].type = fixupAddrElf(addr);
- nanoRelocs[numRelocs].ofstInRam = offset;
- numRelocs++;
- }
- }
-
- uint32_t packedNanoRelocSz = 0;
- app->packedNanoRelocs.data = packNanoRelocs(
- nanoRelocs, numRelocs, &packedNanoRelocSz, verbose);
- app->packedNanoRelocs.size = packedNanoRelocSz;
- success = true;
-out:
- free(nanoRelocs);
- return success;
-}
-
-static int handleAppStatic(const char *fileName, FILE *out, uint32_t layoutFlags, uint64_t appId, bool verbose)
-{
- struct ElfNanoApp app;
-
- if (!loadNanoappElfFile(fileName, &app)
- || !fixupHeaderElf(&app)
- || !genElfNanoRelocs(&app, verbose)) {
- exit(2);
- }
-
- // Construct a single contiguous buffer, with extra room to fit the
- // ImageHeader that will be prepended by finalizeAndWrite(). Note that this
- // will allocate a bit more space than is needed, because some of the data
- // from BinHdr will get discarded.
- // TODO: this should be refactored to just write the binary components in
- // order rather than allocating a big buffer, and moving data around
- size_t bufSize = app.flash.size + app.data.size + app.packedNanoRelocs.size
- + sizeof(struct ImageHeader);
- uint8_t *buf = malloc(bufSize);
- if (!buf) {
- ERR("Failed to allocate %zu bytes for final app", bufSize);
- exit(2);
- }
-
- size_t offset = 0;
- memcpy(buf, app.flash.data, app.flash.size);
- offset += app.flash.size;
- memcpy(&buf[offset], app.data.data, app.data.size);
- offset += app.data.size;
- memcpy(&buf[offset], app.packedNanoRelocs.data, app.packedNanoRelocs.size);
- offset += app.packedNanoRelocs.size;
-
- // Update rel_end in the header to reflect the packed reloc size
- struct BinHdr *hdr = (struct BinHdr *) buf;
- hdr->sect.rel_end = hdr->sect.rel_start + app.packedNanoRelocs.size;
-
- return finalizeAndWrite(buf, offset, bufSize, out, layoutFlags, appId);
- // TODO: should free all memory we allocated... just letting the OS handle
- // it for now
-}
-
static int handleKey(uint8_t **pbuf, uint32_t bufUsed, FILE *out, uint32_t layoutFlags, uint64_t appId, uint64_t keyId)
{
uint8_t *buf = *pbuf;
@@ -905,7 +648,6 @@
const char *layoutName = "app";
const char *prev = NULL;
bool bareData = false;
- bool staticElf = false;
for (int i = 1; i < argc; i++) {
char *end = NULL;
@@ -915,8 +657,6 @@
verbose = true;
else if (!strcmp(argv[i], "-r"))
bareData = true;
- else if (!strcmp(argv[i], "-s"))
- staticElf = true;
else if (!strcmp(argv[i], "-a"))
u64Arg = &appId;
else if (!strcmp(argv[i], "-k"))
@@ -969,9 +709,6 @@
fatalUsage(appName, "Invalid layout name", layoutName);
}
- if (staticElf && layoutId != LAYOUT_APP)
- fatalUsage(appName, "Only app layout is supported for static option", NULL);
-
if (layoutId == LAYOUT_APP && !appId)
fatalUsage(appName, "App layout requires app ID", NULL);
if (layoutId == LAYOUT_KEY && !keyId)
@@ -979,25 +716,22 @@
if (layoutId == LAYOUT_OS && (keyId || appId))
fatalUsage(appName, "OS layout does not need any ID", NULL);
- if (!staticElf) {
- buf = loadFile(posArg[0], &bufUsed);
- fprintf(stderr, "Read %" PRIu32 " bytes\n", bufUsed);
- }
-
- if (!posArg[1])
+ if (!posArg[1]) {
out = stdout;
- else
+ stdlog = stderr;
+ } else {
out = fopen(posArg[1], "w");
+ stdlog = stdout;
+ }
if (!out)
fatalUsage(appName, "failed to create/open output file", posArg[1]);
+ buf = loadFile(posArg[0], &bufUsed);
+ DBG("Read %" PRIu32 " bytes from %s", bufUsed, posArg[0]);
+
switch(layoutId) {
case LAYOUT_APP:
- if (staticElf) {
- ret = handleAppStatic(posArg[0], out, layoutFlags, appId, verbose);
- } else {
- ret = handleApp(&buf, bufUsed, out, layoutFlags, appId, verbose);
- }
+ ret = handleApp(&buf, bufUsed, out, layoutFlags, appId, verbose);
break;
case LAYOUT_KEY:
ret = handleKey(&buf, bufUsed, out, layoutFlags, appId, keyId);