~pixelherodev/knightos

scas: add plan9 object file support v1 PROPOSED

Jacob G-W
Jacob G-W: 1
 scas: add plan9 object file support

 6 files changed, 146 insertions(+), 2 deletions(-)
Export patchset (mbox)
How do I use this?

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 -3
Learn more about email & git
View this thread in the archives

[PATCH] scas: add plan9 object file support Export this patch

Jacob G-W
---
 .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