Skip to content

Commit

Permalink
correctly generate AMaCC ELF by itself
Browse files Browse the repository at this point in the history
Originally, .text was fixed to 4K while the generated ELF by self-
compilation would exceed.

The change fix the problem by allocating .text at runtime, and the
offset to .data section is larger (about 786K), which implies the
code generated by AMaCC must be less than 786K.

Signed-off-by: Jim Huang <[email protected]>
  • Loading branch information
lecopzer authored and jserv committed Mar 18, 2016
1 parent edd1cd1 commit 5008a8a
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 34 deletions.
24 changes: 16 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
CROSS_COMPILE ?= arm-linux-gnueabihf-
CFLAGS = -O0 -Wall
OBJ_DIR = elf
TEST_DIR = ./tests
TEST_DIR = tests
TEST_SRC = $(wildcard $(TEST_DIR)/*.c)
TEST_OBJ = $(TEST_SRC:.c=.o)
PASS_COLOR = \x1b[32;01m
Expand All @@ -17,18 +17,26 @@ amacc: amacc.c
$(CROSS_COMPILE)gcc $(CFLAGS) -fsigned-char -o amacc $? -g -ldl

check: $(BIN) $(TEST_OBJ)
@echo "[ compiled ]"
@echo "[ JIT ]"
@$(ARM_EXEC) ./amacc tests/hello.c
@echo "[ nested ]"
@echo "[ compiled ]"
@$(ARM_EXEC) ./amacc -o $(OBJ_DIR)/hello tests/hello.c
@$(ARM_EXEC) $(OBJ_DIR)/hello
@echo "[ nested ]"
@$(ARM_EXEC) ./amacc amacc.c tests/hello.c

$(TEST_DIR)/%.o: $(TEST_DIR)/%.c $(BIN)
@echo "[*** verify $< <JIT>***]"
@$(ARM_EXEC) ./amacc $< 2
@echo "[*** verify $< <ELF>***]"
$(OBJ_DIR)/amacc: $(BIN)
@$(ARM_EXEC) ./$^ -o $(OBJ_DIR)/amacc amacc.c

$(TEST_DIR)/%.o: $(TEST_DIR)/%.c $(BIN) $(OBJ_DIR)/amacc
@echo "[*** verify $< <JIT>********]"
@$(ARM_EXEC) ./$(BIN) $< 2
@echo "[*** verify $< <ELF>********]"
@mkdir -p $(OBJ_DIR)
@$(ARM_EXEC) ./amacc -o $(OBJ_DIR)/$(notdir $(basename $<)) $<
@$(ARM_EXEC) ./$(BIN) -o $(OBJ_DIR)/$(notdir $(basename $<)) $<
@$(ARM_EXEC) $(OBJ_DIR)/$(notdir $(basename $<)) 2
@echo "[*** verify $< <ELF-self>***]"
@$(ARM_EXEC) ./$(OBJ_DIR)/amacc $< 2
@/bin/echo -e "$(PASS_COLOR)$< pass$(NO_COLOR)\n"

clean:
Expand Down
67 changes: 41 additions & 26 deletions amacc.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ int src; // print source and assembly flag
int verbose; // print executed instructions
int elf; // print ELF format
int elf_fd;
int rodata_align_off;

// identifier
struct ident_s {
Expand Down Expand Up @@ -163,6 +164,7 @@ void next()
if (tk == '"') *data++ = ival;
}
++p;
// if .text too big rodata v_addr will overlap it, add that to stay away from .text
if (tk == '"') ival = (int) pp; else tk = Num;
return;
case '=': if (*p == '=') { ++p; tk = Eq; } else tk = Assign; return;
Expand Down Expand Up @@ -1054,6 +1056,7 @@ int elf32(int poolsz, int *start)
char *to_got_movw, *to_got_movt;
char **got_func_slot;
int got_size, rodata_size, sh_dynstr_idx, sh_dynsym_idx;
int code_size_align;

code = malloc(poolsz);
buf = malloc(poolsz);
Expand Down Expand Up @@ -1105,7 +1108,7 @@ int elf32(int poolsz, int *start)
code_off = o - buf; // 0x1000
// must add a value >= 4. sometimes first codegen size is not equal
// to second codegen
code_size = je - code + 8;
code_size = je - code + 128;
rel_size = 8 * FUNC_NUM;
rel_off = code_off + code_size;
rel_addr = o + code_size;
Expand All @@ -1116,7 +1119,8 @@ int elf32(int poolsz, int *start)

code_addr = o;
o++;
o = (char *) (((int) o + ALIGN - 1) & -ALIGN); // to 0x2000
code_size_align = (((int) code_size + ALIGN - 1) & -ALIGN);
o = (char *)(((int)(o + code_size) + ALIGN - 1) & -ALIGN); // to 0x2000
memcpy(code_addr, code, 0x1000);
*(int *) entry = (int) code_addr;

Expand All @@ -1134,27 +1138,37 @@ int elf32(int poolsz, int *start)
// elf_phdr because ld.so must be able to see it
// PT_LOAD for code
to = phdr;
gen_PT(to, PT_LOAD, 0, (int) buf, 0x2000, PF_X | PF_R, 0x1000);
// code_idx
gen_PT(to, PT_LOAD, 0, (int) buf, code_size_align + 0x1000,
PF_X | PF_R, 0x1000);
to = to+ PHDR_SIZE;
code_size_align = code_size_align - 0x1000;
// PT_LOAD for data
gen_PT(to, PT_LOAD, pt_dyn_off, (int) pt_dyn, 4096, PF_W | PF_R, 0x1000);
// data_idx
gen_PT(to, PT_LOAD, pt_dyn_off, (int) pt_dyn + code_size_align, 4096,
PF_W | PF_R, 0x1000);
to = to + PHDR_SIZE;

// PT_INTERP
gen_PT(to, PT_INTERP, linker_off, (int) linker,
// interp_idx
gen_PT(to, PT_INTERP, linker_off, (int) linker + code_size_align,
25 , PF_R, 0x1);
to = to + PHDR_SIZE;

// PT_DYNAMIC
gen_PT(to, PT_DYNAMIC, pt_dyn_off, (int) pt_dyn,
gen_PT(to, PT_DYNAMIC, pt_dyn_off, (int) pt_dyn + code_size_align,
pt_dyn_size , PF_R | PF_W, 4);
to = to + PHDR_SIZE;

// offset and v_addr must align for 0xFFF(or 0xFFFF?)
rodata_off = 0x3000 | ((int) _data & 0xfff);
rodata_off = (pt_dyn_off + 0x1000) | ((int) _data & 0xfff);
// PT_LOAD for others data
// FIXME: .text and .rodata will be at least 3 * 256 * 1024 =
// 3 * 2^18 bytes = 0xc0000 offset
// so now AMaCC can only generate code which code size is less than
// about 786K
gen_PT(to, PT_LOAD, rodata_off, (int)_data,
_data_end - _data, PF_X | PF_R, 1);
_data_end - _data, PF_X | PF_R | PF_W, 1);
to = to + PHDR_SIZE;

// .shstrtab (embedded in PT_LOAD of data)
Expand Down Expand Up @@ -1227,13 +1241,14 @@ int elf32(int poolsz, int *start)
got_off = dynsym_off + dynsym_size + gap;
*(int *) data = (int) pt_dyn; data = data + 4;
data = data + 4; // reserved 2 and 3 entry for linker
to_got_movw = data; to_got_movt = data; // the address handling dynamic
// linking, plt must jump here
to_got_movw = data + code_size_align;
to_got_movt = data + code_size_align; // the address manupulates dynamic
// linking, plt must jump here
data = data + 4; // reserved 2 and 3 entry for linker
// .got function slot
got_func_slot = malloc(FUNC_NUM);
for (i = 0; i < FUNC_NUM; i++) {
got_func_slot[i] = data;
got_func_slot[i] = data + code_size_align;
*(int *) data = (int) plt_addr; data = data + 4;
}
data = data + 4; // end with 0x0
Expand Down Expand Up @@ -1278,20 +1293,21 @@ int elf32(int poolsz, int *start)

// .rodata
rodata_size = _data_end - _data;
o = o + rodata_off - 0x3000;
o = o + (rodata_off - (pt_dyn_off + 0x1000)); // rodata_off has align x bytes
memcpy(o, _data, rodata_size);
o = o + rodata_size;
*(int *) e_shoff = (int)(o - buf);
// .dynamic (embedded in PT_LOAD of data)
to = pt_dyn;
*(int *) to = 5; to = to + 4; *(int *) to = (int) dynstr_addr; to = to + 4;
*(int *) to = 5; to = to + 4; *(int *) to = (int) dynstr_addr +
code_size_align; to = to + 4;
*(int *) to = 10; to = to + 4; *(int *) to = dynstr_size; to = to + 4;
*(int *) to = 6; to = to + 4; *(int *) to = (int) dynsym_addr; to = to + 4;
*(int *) to = 6; to = to + 4; *(int *) to = (int) dynsym_addr + code_size_align; to = to + 4;
*(int *) to = 11; to = to + 4; *(int *) to = 16; to = to + 4;
*(int *) to = 17; to = to + 4; *(int *) to = (int) rel_addr; to = to + 4;
*(int *) to = 18; to = to + 4; *(int *) to = rel_size; to = to + 4;
*(int *) to = 19; to = to + 4; *(int *) to = 8; to = to + 4;
*(int *) to = 3; to = to + 4; *(int *) to = (int) got_addr; to = to + 4;
*(int *) to = 3; to = to + 4; *(int *) to = (int) got_addr + code_size_align; to = to + 4;
*(int *) to = 2; to = to + 4; *(int *) to = rel_size; to = to + 4;
*(int *) to = 20; to = to + 4; *(int *) to = 17; to = to + 4;
*(int *) to = 23; to = to + 4; *(int *) to = (int) rel_addr; to = to + 4;
Expand Down Expand Up @@ -1337,27 +1353,27 @@ int elf32(int poolsz, int *start)
o = o + SHDR_SIZE;

// sh_data_idx
gen_SH(o, SHT_PROGBITS, 17, pt_dyn_off, (int) pt_dyn, 0x1000,
gen_SH(o, SHT_PROGBITS, 17, pt_dyn_off, (int) pt_dyn + code_size_align, 0x1000,
0, 0, SHF_ALLOC | SHF_WRITE, 4, 0);
o = o + SHDR_SIZE;

sh_dynstr_idx =
gen_SH(o, SHT_STRTAB, 48, dynstr_off, (int) dynstr_addr, dynstr_size,
gen_SH(o, SHT_STRTAB, 48, dynstr_off, (int) dynstr_addr + code_size_align, dynstr_size,
0, 0, SHF_ALLOC, 1, 0);
o = o + SHDR_SIZE;

sh_dynsym_idx =
gen_SH(o, SHT_DYNSYM, 56, dynsym_off, (int) dynsym_addr, dynsym_size,
gen_SH(o, SHT_DYNSYM, 56, dynsym_off, (int) dynsym_addr + code_size_align, dynsym_size,
sh_dynstr_idx, 1, SHF_ALLOC, 4, 0x10);
o = o + SHDR_SIZE;

// sh_dynamic_idx
gen_SH(o, SHT_DYNAMIC, 23, pt_dyn_off, (int) pt_dyn, pt_dyn_size,
gen_SH(o, SHT_DYNAMIC, 23, pt_dyn_off, (int) pt_dyn + code_size_align, pt_dyn_size,
sh_dynstr_idx, 0, SHF_ALLOC | SHF_WRITE, 4, 0);
o = o + SHDR_SIZE;

// sh_interp_idx
gen_SH(o, SHT_PROGBITS, 64, linker_off, (int) linker, 25,
gen_SH(o, SHT_PROGBITS, 64, linker_off, (int) linker + code_size_align, 25,
0, 0, SHF_ALLOC, 1, 0);
o = o + SHDR_SIZE;

Expand All @@ -1372,7 +1388,7 @@ int elf32(int poolsz, int *start)
o = o + SHDR_SIZE;

// sh_got_idx
gen_SH(o, SHT_PROGBITS, 86, got_off, (int)_data, got_size,
gen_SH(o, SHT_PROGBITS, 86, got_off, (int)got_addr + code_size_align, got_size,
0, 0, SHF_ALLOC | SHF_WRITE, 4, 4);
o = o + SHDR_SIZE;

Expand Down Expand Up @@ -1416,13 +1432,13 @@ int main(int argc, char **argv)
printf("could not open(%s)\n", *argv); return -1;
}

poolsz = 256 * 1024; // arbitrary size
if (!(sym = malloc(poolsz))) {
printf("could not malloc(%d) symbol area\n", poolsz); return -1;
}
poolsz = 256*1024; // arbitrary size
if (!(text = le = e = malloc(poolsz))) {
printf("could not malloc(%d) text area\n", poolsz); return -1;
}
if (!(sym = malloc(poolsz))) {
printf("could not malloc(%d) symbol area\n", poolsz); return -1;
}
if (!(_data = data = malloc(poolsz))) {
printf("could not malloc(%d) data area\n", poolsz); return -1;
}
Expand Down Expand Up @@ -1476,7 +1492,6 @@ int main(int argc, char **argv)
// add primitive types
tsize[tnew++] = sizeof(char);
tsize[tnew++] = sizeof(int);

// parse declarations
line = 1;
next();
Expand Down

0 comments on commit 5008a8a

Please sign in to comment.