# HG changeset patch
# User lost
# Date 1232513672 0
# Node ID 460d96987670f48f23b41927356ed00474bb60c6
# Parent 96a35a4245f338cff36ba2a0e41a0e369559fede
parse linking scripts
diff -r 96a35a4245f3 -r 460d96987670 src/Makefile.am
--- a/src/Makefile.am Wed Jan 21 03:15:49 2009 +0000
+++ b/src/Makefile.am Wed Jan 21 04:54:32 2009 +0000
@@ -1,3 +1,3 @@
bin_PROGRAMS = lwlink
-lwlink_SOURCES = main.c lwlink.c util.c readfiles.c expr.c
+lwlink_SOURCES = main.c lwlink.c util.c readfiles.c expr.c script.c
EXTRA_DIST = lwlink.h util.h expr.h
diff -r 96a35a4245f3 -r 460d96987670 src/lwlink.c
--- a/src/lwlink.c Wed Jan 21 03:15:49 2009 +0000
+++ b/src/lwlink.c Wed Jan 21 04:54:32 2009 +0000
@@ -38,6 +38,7 @@
int debug_level = 0;
int outformat = OUTPUT_DECB;
char *outfile = NULL;
+char *scriptfile = NULL;
fileinfo_t **inputfiles = NULL;
int ninputfiles = 0;
diff -r 96a35a4245f3 -r 460d96987670 src/lwlink.h
--- a/src/lwlink.h Wed Jan 21 03:15:49 2009 +0000
+++ b/src/lwlink.h Wed Jan 21 04:54:32 2009 +0000
@@ -80,6 +80,7 @@
extern char *outfile;
extern int ninputfiles;
extern fileinfo_t **inputfiles;
+extern char *scriptfile;
#define __lwlink_E__ extern
#else
@@ -89,4 +90,24 @@
__lwlink_E__ void add_input_file(char *fn);
#undef __lwlink_E__
+
+struct scriptline_s
+{
+ char *sectname; // name of section, NULL for wildcard
+ int loadat; // address to load at (or -1)
+ int noflags; // flags to NOT have
+ int yesflags; // flags to HAVE
+};
+
+typedef struct
+{
+ int nlines; // number of lines in the script
+ struct scriptline_s *lines; // the parsed script lines (section)
+ int padsize; // the size to pad to, -1 for none
+} linkscript_t;
+
+#ifndef __script_c_seen__
+extern linkscript_t linkscript;
+#endif
+
#endif //__lwlink_h_seen__
diff -r 96a35a4245f3 -r 460d96987670 src/main.c
--- a/src/main.c Wed Jan 21 03:15:49 2009 +0000
+++ b/src/main.c Wed Jan 21 04:54:32 2009 +0000
@@ -46,6 +46,11 @@
outfile = arg;
break;
+ case 's':
+ // script file
+ scriptfile = arg;
+ break;
+
case 'd':
// debug
debug_level++;
@@ -101,6 +106,8 @@
"Generate DECB .bin format output, equivalent of --format=decb"},
{ "raw", 'r', 0, 0,
"Generate raw binary format output, equivalent of --format=raw"},
+ { "script", 's', 0, 0,
+ "Specify the linking script (overrides the build in defaults)"},
{ 0 }
};
@@ -113,6 +120,7 @@
};
extern void read_files(void);
+extern void setup_script(void);
// main function; parse command line, set up assembler state, and run the
// assembler on the first file
@@ -125,6 +133,8 @@
exit(1);
}
+ setup_script();
+
// read the input files
read_files();
diff -r 96a35a4245f3 -r 460d96987670 src/script.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/script.c Wed Jan 21 04:54:32 2009 +0000
@@ -0,0 +1,236 @@
+/*
+script.c
+Copyright © 2008 William Astle
+
+This file is part of LWLINK.
+
+LWLINK is free software: you can redistribute it and/or modify it under the
+terms of the GNU General Public License as published by the Free Software
+Foundation, either version 3 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+more details.
+
+You should have received a copy of the GNU General Public License along with
+this program. If not, see .
+
+
+Read and parse linker scripts
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include
+#include
+#include
+#include
+
+#include "lwlink.h"
+#include "util.h"
+
+// the built-in DECB target linker script
+static char *decb_script =
+ "section init load at 2000\n"
+ "section code\n"
+ "section *,!bss\n"
+ "section *,bss\n"
+ ;
+
+// the built-in RAW target linker script
+static char *raw_script =
+ "section init load at 0000\n"
+ "section code\n"
+ "section *,!bss\n"
+ "section *,bss\n"
+ ;
+
+// the "simple" script
+static char *simple_script =
+ "section *,!bss\n"
+ "section *,bss\n"
+ ;
+
+linkscript_t linkscript = { 0, NULL, -1 };
+
+void setup_script()
+{
+ char *script;
+ long size;
+
+ // read the file if needed
+ if (scriptfile)
+ {
+ FILE *f;
+ long bread;
+
+ f = fopen(scriptfile, "rb");
+ if (!f)
+ {
+ fprintf(stderr, "Can't open file %s:", scriptfile);
+ perror("");
+ exit(1);
+ }
+ fseek(f, 0, SEEK_END);
+ size = ftell(f);
+ rewind(f);
+
+ script = lw_malloc(size + 2);
+
+ bread = fread(script, 1, size, f);
+ if (bread < size)
+ {
+ fprintf(stderr, "Short read on file %s (%ld/%ld):", scriptfile, bread, size);
+ perror("");
+ exit(1);
+ }
+ fclose(f);
+
+ script[size] = '\n';
+ script[size + 1] = '\0';
+ }
+ else
+ {
+ // fetch defaults based on output mode
+ switch (outformat)
+ {
+ case OUTPUT_RAW:
+ script = raw_script;
+ break;
+
+ case OUTPUT_DECB:
+ script = decb_script;
+ break;
+
+ default:
+ script = simple_script;
+ break;
+ }
+
+ size = strlen(script);
+ }
+
+ // now parse the script file
+ while (*script)
+ {
+ char *ptr, *ptr2, *line;
+
+ for (ptr = script; *ptr && *ptr != '\n' && *ptr != '\r'; ptr++)
+ /* do nothing */ ;
+
+ line = lw_malloc(ptr - script + 1);
+ memcpy(line, script, ptr - script);
+ line[ptr - script] = '\0';
+
+ // skip line terms
+ for (script = ptr + 1; *script == '\n' || *script == '\r'; script++)
+ /* do nothing */ ;
+
+ // ignore leading whitespace
+ for (ptr = line; *ptr && isspace(*ptr); ptr++)
+ /* do nothing */ ;
+
+ // ignore blank lines
+ if (!*ptr)
+ continue;
+
+ for (ptr = line; *ptr && !isspace(*ptr); ptr++)
+ /* do nothing */ ;
+
+ // now ptr points to the char past the first word
+ // NUL it out
+ if (*ptr)
+ *ptr++ = '\0';
+
+ // skip spaces after the first word
+ for ( ; *ptr && isspace(*ptr); ptr++)
+ /* do nothing */ ;
+
+ if (!strcmp(line, "pad"))
+ {
+ // padding
+ // parse the hex number and stow it
+ linkscript.padsize = strtol(ptr, NULL, 16);
+ if (linkscript.padsize < 0)
+ linkscript.padsize = 0;
+ }
+ else if (!strcmp(line, "section"))
+ {
+ // section
+ // parse out the section name and flags
+ for (ptr2 = ptr; *ptr2 && !isspace(*ptr2); ptr2++)
+ /* do nothing */ ;
+
+ if (*ptr2)
+ *ptr2++ = '\0';
+
+ while (*ptr2 && isspace(*ptr2))
+ ptr2++;
+
+ // ptr now points to the section name and flags and ptr2
+ // to the first non-space character following
+
+ // then look for "load " clause
+ if (*ptr2)
+ {
+ if (!strncmp(ptr2, "load", 4))
+ {
+ ptr2 += 4;
+ while (*ptr2 && isspace(*ptr2))
+ ptr2++;
+
+ }
+ else
+ {
+ fprintf(stderr, "%s: bad script\n", scriptfile);
+ exit(1);
+ }
+ }
+
+ // now ptr2 points to the load address if there is one
+ // or NUL if not
+ linkscript.lines = lw_realloc(linkscript.lines, sizeof(struct scriptline_s) * (linkscript.nlines + 1));
+
+ linkscript.lines[linkscript.nlines].noflags = 0;
+ linkscript.lines[linkscript.nlines].yesflags = 0;
+ if (*ptr2)
+ linkscript.lines[linkscript.nlines].loadat = strtol(ptr2, NULL, 16);
+ else
+ linkscript.lines[linkscript.nlines].loadat = -1;
+ for (ptr2 = ptr; *ptr2 && *ptr2 != ','; ptr2++)
+ /* do nothing */ ;
+ if (*ptr2)
+ {
+ *ptr2++ = '\0';
+ if (!strcmp(ptr2, "!bss"))
+ {
+ linkscript.lines[linkscript.nlines].noflags = SECTION_BSS;
+ }
+ else if (!strcmp(ptr2, "bss"))
+ {
+ linkscript.lines[linkscript.nlines].yesflags = SECTION_BSS;
+ }
+ else
+ {
+ fprintf(stderr, "%s: bad script\n", scriptfile);
+ exit(1);
+ }
+ }
+ linkscript.lines[linkscript.nlines].sectname = lw_strdup(ptr);
+ linkscript.nlines++;
+ }
+ else
+ {
+ fprintf(stderr, "%s: bad script\n", scriptfile);
+ exit(1);
+ }
+ lw_free(line);
+ }
+
+ if (scriptfile)
+ lw_free(script);
+}