Jacob G-W: 1 scas: add plan9 object file support 6 files changed, 146 insertions(+), 2 deletions(-)
Copy & paste the following snippet into your terminal to import this patchset into git:
curl -s https://lists.sr.ht/~pixelherodev/knightos/patches/23774/mbox | git am -3Learn more about email & git
--- .gitignore | 1 + Makefile | 4 +- include/linker.h | 1 + include/plan9.h | 2 + linker/plan9.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++ scas.c | 3 ++ 6 files changed, 146 insertions(+), 2 deletions(-) create mode 100644 include/plan9.h create mode 100644 linker/plan9.c diff --git a/.gitignore b/.gitignore index 00ae34f..e5850b3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ *.swp *.o +*.6 bin/ *.rom test/ diff --git a/Makefile b/Makefile index fd28234..142739f 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ CFLAGS=-Iinclude/ -O2 -Ibin/ -Wall -Wextra -pedantic -std=c99 -D_XOPEN_SOURCE=70 ASSEMBLER=assembler/privatize.c assembler/directives.c assembler/assembler.c COMMON=bin/amd64.c bin/z80.c bin/arm64.c common/functions.c common/hashtable.c common/expression.c common/list.c common/operators.c common/runtime.c common/stringop.c common/errors.c common/stack.c common/format.c common/instructions.c common/log.c common/match.c common/md5.c common/objects.c common/readline.c -LINKER=linker/8xp.c linker/bin.c linker/linker.c linker/merge.c +LINKER=linker/8xp.c linker/plan9.c linker/bin.c linker/linker.c linker/merge.c SOURCES=$(ASSEMBLER) $(COMMON) $(LINKER) all:bin/scas bin/scdump bin/scwrap @@ -70,7 +70,7 @@ bin/generate_tables: tables/generate.c mkdir -p bin/ $(CC) $(CFLAGS) $< -o $@ -$(SOURCES:.c=.o) scas.o: bin/z80.h bin/amd64.h bin/arm64.h include/linker.h include/match.h include/format.h include/merge.h include/list.h include/assembler.h include/md5.h include/objects.h include/8xp.h include/stack.h include/bin.h include/directives.h include/errors.h include/instructions.h include/readline.h include/runtime.h include/stringop.h include/hashtable.h include/functions.h include/log.h include/expression.h include/privatize.h include/operators.h +$(SOURCES:.c=.o) scas.o: bin/z80.h bin/amd64.h bin/arm64.h include/linker.h include/match.h include/format.h include/merge.h include/list.h include/assembler.h include/md5.h include/objects.h include/8xp.h include/plan9.h include/stack.h include/bin.h include/directives.h include/errors.h include/instructions.h include/readline.h include/runtime.h include/stringop.h include/hashtable.h include/functions.h include/log.h include/expression.h include/privatize.h include/operators.h .c.o: $(CC) $(CFLAGS) -c $< -o $@ diff --git a/include/linker.h b/include/linker.h index e6fa184..dfc4bfb 100644 --- a/include/linker.h +++ b/include/linker.h @@ -9,4 +9,5 @@ struct linker_settings { format_writer write_output; }; +list_t *symbols_gather(list_t *areas, list_t *errors); void link_objects(FILE *output, list_t *objects, linker_settings_t *settings); diff --git a/include/plan9.h b/include/plan9.h new file mode 100644 index 0000000..7686da8 --- /dev/null +++ b/include/plan9.h @@ -0,0 +1,2 @@ +int output_plan9(FILE *f, object_t *object, linker_settings_t *settings); + diff --git a/linker/plan9.c b/linker/plan9.c new file mode 100644 index 0000000..6a14171 --- /dev/null +++ b/linker/plan9.c @@ -0,0 +1,137 @@ +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include "list.h" +#include "stack.h" +#include "expression.h" +#include "objects.h" +#include "linker.h" +#include "plan9.h" +#include "instructions.h" +#include "runtime.h" +#include "log.h" + +#define HDR_MAGIC 0x00008000 /* header expansion */ + +#define _MAGIC(f, b) ((f)|((((4*(b))+0)*(b))+7)) +#define A_MAGIC _MAGIC(0, 8) /* 68020 */ +#define I_MAGIC _MAGIC(0, 11) /* intel 386 */ +#define J_MAGIC _MAGIC(0, 12) /* intel 960 (retired) */ +#define K_MAGIC _MAGIC(0, 13) /* sparc */ +#define V_MAGIC _MAGIC(0, 16) /* mips 3000 BE */ +#define X_MAGIC _MAGIC(0, 17) /* att dsp 3210 (retired) */ +#define M_MAGIC _MAGIC(0, 18) /* mips 4000 BE */ +#define D_MAGIC _MAGIC(0, 19) /* amd 29000 (retired) */ +#define E_MAGIC _MAGIC(0, 20) /* arm */ +#define Q_MAGIC _MAGIC(0, 21) /* powerpc */ +#define N_MAGIC _MAGIC(0, 22) /* mips 4000 LE */ +#define L_MAGIC _MAGIC(0, 23) /* dec alpha (retired) */ +#define P_MAGIC _MAGIC(0, 24) /* mips 3000 LE */ +#define U_MAGIC _MAGIC(0, 25) /* sparc64 */ +#define S_MAGIC _MAGIC(HDR_MAGIC, 26) /* amd64 */ +#define T_MAGIC _MAGIC(HDR_MAGIC, 27) /* powerpc64 */ +#define R_MAGIC _MAGIC(HDR_MAGIC, 28) /* arm64 */ + +void write_be32(FILE *f, uint32_t value) { + uint8_t bytes[4]; + bytes[0] = (value >> 24) & 0xff; + bytes[1] = (value >> 16) & 0xff; + bytes[2] = (value >> 8) & 0xff; + bytes[3] = (value) & 0xff; + fwrite(bytes, 4, 1, f); +} +void write_be64(FILE *f, uint64_t value) { + write_be32(f, (value >> 32) & 0xffffffff); + write_be32(f, (value) & 0xffffffff); +} + +// returns 1 on failure +uint32_t get_magic(char* arch) { + if (strcmp(arch, "amd64")) { + return S_MAGIC; + } + if (strcmp(arch, "arm64")) { + return R_MAGIC; + } + return 1; +} + +int output_plan9(FILE *f, object_t *object, linker_settings_t *settings) { + area_t* data = 0; + area_t* text = 0; + uint32_t bss_len = 0; + uint32_t syms_len = 0; + uint64_t entry = 0; + + for (unsigned int i = 0; i < object->areas->length; i++){ + area_t* area = object->areas->items[i]; + if (strcmp("_CODE", area->name) == 0) { + text = area; + relocate_area(text, 0x200028, true); + } else if (strcmp("_DATA", area->name) == 0) { + data = area; + relocate_area(data, 0x400000, true); + } else { + scas_log(L_ERROR, "unknown section name for plan9 a.out format: %s", area->name); + return 1; + } + } + if (text == 0) { + scas_log(L_ERROR, "plan9 a.out format needs text section"); + return 1; + } + + // the header + uint32_t magic = get_magic(scas_runtime.arch); + bool is64 = (magic & HDR_MAGIC) >> 15 == 1; + if (magic == 1) return 1; + write_be32(f, magic); + write_be32(f, text->data_length); + if (data != 0) + write_be32(f, data->data_length); + else + write_be32(f, 0); + write_be32(f, bss_len); + write_be32(f, syms_len); + write_be32(f, entry); + write_be32(f, 0); // size of pc/sp offset table + write_be32(f, 0); // size of pc/line number table + if (is64) + write_be64(f, entry); + + // write the text + fwrite(text->data, 1, text->data_length, f); + // write the data (if there is any) + if (data != 0) + fwrite(data->data, 1, data->data_length, f); + // write the symbols + uint32_t symseclen = 0; + list_t* symbols = symbols_gather(object->areas, settings->errors); + for (unsigned int i = 0; i < symbols->length; i++){ + symbol_t* s = symbols->items[i]; + if (is64) + write_be64(f, s->value); + else + write_be32(f, s->value); + fputc('T' | 0x80, f); // TODO actual type not just text + int namelen = strlen(s->name) + 1; + fwrite(s->name, sizeof(char), namelen, f); + if (strcmp("start", s->name) == 0) + entry = s->value; + symseclen += 8 + 1 + namelen; + } + // write back into the header + fseek(f, 4 * 4, SEEK_SET); + write_be32(f, symseclen); + fseek(f, 5 * 4, SEEK_SET); + write_be32(f, entry); + if (is64) { + fseek(f, 8 * 4, SEEK_SET); + write_be64(f, entry); + } + fseek(f, 0, SEEK_END); + + return 0; +} diff --git a/scas.c b/scas.c index b97a488..b55fd3c 100644 --- a/scas.c +++ b/scas.c @@ -18,6 +18,7 @@ #include "linker.h" #include "assembler.h" #include "8xp.h" +#include "plan9.h" #include "bin.h" #include "merge.h" #include "runtime.h" @@ -164,6 +165,8 @@ bool parse_flag(const char *flag) { scas_runtime.options.output_format = output_bin; } else if (strcmp(value, "8xp") == 0){ scas_runtime.options.output_format = output_8xp; + } else if (strcmp(value, "plan9") == 0){ + scas_runtime.options.output_format = output_plan9; } else { scas_log(L_ERROR, "Unknown output format %s", value); return false; -- 2.29.3