mcc

mcc is a machine code compiler.

Log | Files | << Repositories


tree 3d5e55f9d2ee3fb466f125d93b47cdfdb858f482
parent 700d4c4b5b2021938fa7380afe9497a92f06bb9d
author esote <esote.net@gmail.com> 1560709515 -0500
committer esote <esote.net@gmail.com> 1560709515 -0500
gpgsig -----BEGIN PGP SIGNATURE-----
 
 iHUEABYIAB0WIQTXAxYDuIzimYoNSPuhTmRAjzzC8gUCXSArKAAKCRChTmRAjzzC
 8gh7AQC1sU6y0K53c8Agqyjo1CSKOYgZLih32D4QOiZmlbTo3gEA1jnqPvDYRzJn
 1SHJDaMKiF1ir091MQOMWjxpf9hxzgc=
 =LHpr
 -----END PGP SIGNATURE-----

Options for custom bss and text addresses

 README |  8 ++++---
 mcc.1  |  8 +++++++
 mcc.c  | 80 +++++++++++++++++++++++++++++++++++++++++++++++-------------------
 3 files changed, 70 insertions(+), 26 deletions(-)

diff --git a/README b/README
index d0ce109..f86604b 100644
--- a/README
+++ b/README
@@ -2,7 +2,7 @@ NAME
 	mcc - machine code compiler
 
 SYNOPSIS
-	mcc [-3s] [-m memsize] [-o file] file
+	mcc [-3s] [-b addr] [-m memsize] [-o file] [-t addr] file
 
 DESCRIPTION
 	mcc is a machine code compiler. It reads ASCII text '0' and '1' mapping
@@ -22,8 +22,10 @@ DESCRIPTION
 
 	In 64-bit mode the .bss and .text sections start at 0x402000 and
 	0x401000 respectively, and in 32-bit mode 0x804a000 and 0x8049000
-	respectively. Program header segment alignment is set to 0x1000 (the
-	page size on most systems).
+	respectively. Use the -b and -t options to specify custom addresses.
+
+	Program header segment alignment is set to 0x1000 (the page size on most
+	systems).
 
 	.bss is aligned to a 16-byte constraint and .text to an 8-byte
 	constraint.
diff --git a/mcc.1 b/mcc.1
index 24fd57a..6cc99ec 100644
--- a/mcc.1
+++ b/mcc.1
@@ -23,8 +23,10 @@
 .Sh SYNOPSIS
 .Nm mcc
 .Op Fl 3s
+.Op Fl b Ar addr
 .Op Fl m Ar memsize
 .Op Fl o Ar file
+.Op Fl t Ar addr
 file
 .Sh DESCRIPTION
 .Nm mcc
@@ -54,6 +56,12 @@ executable.
 In 64-bit mode the .bss and .text sections start at 0x402000 and
 0x401000 respectively, and in 32-bit mode 0x804a000 and 0x8049000
 respectively.
+Use the
+.Fl b
+and
+.Fl t
+options to specify custom addresses.
+.Pp
 Program header segment alignment is set to 0x1000 (the page size on most
 systems).
 .Pp
diff --git a/mcc.c b/mcc.c
index 4f78314..a17f2e0 100644
--- a/mcc.c
+++ b/mcc.c
@@ -43,36 +43,48 @@ main(int argc, char *argv[])
 	char *end;
 	char const *iname;
 	char const *oname;
-	uint64_t len;
-	uint64_t mem;
-	int use_64;
 	int ch;
+	int use_64;
+	int use_bss_addr;
+	int use_text_addr;
 
 	opts.self_m = 0;
+	opts.mem.n64 = 0;
+	opts.bss_vaddr.n64 = 0x402000;
+	opts.text_vaddr.n64 = 0x401000;
 
 	oname = "a.out";
-	mem = 0;
 
 	/* default 64-bit */
 	use_64 = 1;
-	opts.bss_vaddr.n64 = 0x402000;
-	opts.text_vaddr.n64 = 0x401000;
 
-	while ((ch = getopt(argc, argv, "3m:o:s")) != -1) {
+	use_bss_addr = 0;
+	use_text_addr = 0;
+
+	while ((ch = getopt(argc, argv, "3b:m:o:st:")) != -1) {
 		switch (ch) {
 		case '3':
 			use_64 = 0;
-			opts.bss_vaddr.n32 = 0x804a000;
-			opts.text_vaddr.n32 = 0x8049000;
+			break;
+		case 'b':
+			opts.bss_vaddr.n64 = strtoull(optarg, &end, 0);
+
+			if (errno == EINVAL || errno == ERANGE) {
+				err(1, "bss address invalid");
+			} else if (optarg == end) {
+				err(1, "no bss address read");
+			}
+
+			use_bss_addr = 1;
 			break;
 		case 'm':
-			mem = strtoull(optarg, &end, 10);
+			opts.mem.n64 = strtoull(optarg, &end, 10);
 
 			if (errno == EINVAL || errno == ERANGE) {
 				err(1, "memsize invalid");
 			} else if (optarg == end) {
 				errx(1, "no memsize read");
-			} else if (mem == 0) {
+			} else if (opts.mem.n64 == 0) {
 				warnx("if memsize is zero no .bss section will "
 					"be written");
 			}
@@ -84,18 +96,26 @@ main(int argc, char *argv[])
 		case 's':
 			opts.self_m = 1;
 			break;
+		case 't':
+			opts.text_vaddr.n64 = strtoull(optarg, &end, 0);
+
+			if (errno == EINVAL || errno == ERANGE) {
+				err(1, "text address invalid");
+			} else if (optarg == end) {
+				err(1, "no text address read");
+			}
+
+			use_text_addr = 1;
+			break;
 		default:
 			(void)fprintf(stderr,
-				"usage: %s [-3s] [-m memsize] [-o file] file\n",
+				"usage: %s [-3s] [-b addr] [-m memsize] "
+				"[-o file] [-t addr] file\n",
 				argv[0]);
 			return 1;
 		}
 	}
 
-	if (!use_64 && mem > UINT32_MAX) {
-		warnx("memsize may overflow");
-	}
-
 	argv += optind;
 
 	if ((iname = *argv) == NULL) {
@@ -110,20 +130,34 @@ main(int argc, char *argv[])
 		err(1, "open out");
 	}
 
-	len = byte_len(in);
+	opts.len.n64 = byte_len(in);
+
+	if (!use_64) {
+		if (opts.mem.n64 > UINT32_MAX) {
+			warnx("memsize is larger than 32 bits");
+		}
+
+		if (opts.len.n64 > UINT32_MAX) {
+			warnx("input file byte length is larger than 32 bits");
+		}
+
+		if (!use_bss_addr) {
+			opts.bss_vaddr.n32 = 0x804a000;
+		} else if (opts.bss_vaddr.n64 > UINT32_MAX) {
+			warnx("bss address is larger than 32 bits");
+		}
 
-	if (!use_64 && len > UINT32_MAX) {
-		warnx("input file byte length may overflow");
+		if (!use_text_addr) {
+			opts.text_vaddr.n32 = 0x8049000;
+		} else if (opts.text_vaddr.n64 > UINT32_MAX) {
+			warnx("text address is larger than 32 bits");
+		}
 	}
 
 	if (use_64) {
-		opts.mem.n64 = mem;
-		opts.len.n64 = len;
 		write_ehdr64(out, &opts);
 		write_phdr64_text(out, &opts);
 	} else {
-		opts.mem.n32 = (uint32_t)mem;
-		opts.len.n32 = (uint32_t)len;
 		write_ehdr32(out, &opts);
 		write_phdr32_text(out, &opts);
 	}