From 4c1c09cb191f60159b7753a6d099074596bd952a Mon Sep 17 00:00:00 2001 From: Ali Gholami Rudi Date: Thu, 7 Apr 2016 18:10:22 +0430 Subject: [PATCH] neatcc top-level makefile --- Makefile | 59 +++++++++++++++++ demo/Makefile | 13 ++++ demo/test.c | 7 ++ neatdbg/Makefile | 13 ++++ neatdbg/coredump.c | 119 ++++++++++++++++++++++++++++++++++ neatdbg/elfloc.c | 183 +++++++++++++++++++++++++++++++++++++++++++++++++++++ neatrun/Makefile | 16 +++++ neatrun/neatcc.c | 43 +++++++++++++ 8 files changed, 453 insertions(+) create mode 100644 Makefile create mode 100644 demo/Makefile create mode 100644 demo/test.c create mode 100644 neatdbg/Makefile create mode 100644 neatdbg/coredump.c create mode 100644 neatdbg/elfloc.c create mode 100644 neatrun/Makefile create mode 100644 neatrun/neatcc.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..de11de3 --- /dev/null +++ b/Makefile @@ -0,0 +1,59 @@ +# Neatcc top-level Makefile + +# output architecture: x64, x86, arm +OUT = x64 + +BASE = $(PWD) + +all: help + +help: + @echo "Neatcc top-level makefile" + @echo + @echo " init Initialise git repositories" + @echo " neat Compile the programs" + @echo " pull Update git repositories" + @echo " clean Remove the generated files" + @echo + +init: + @test -d neatcc || git clone git://repo.or.cz/neatcc.git + @test -d neatld || git clone git://repo.or.cz/ld.git neatld + @test -d neatlibc || git clone git://repo.or.cz/neatlibc.git + @test -d neatas || git clone git://repo.or.cz/neatas.git + +pull: + cd neatcc && git pull + cd neatld && git pull + cd neatlibc && git pull + cd neatas && git pull + git pull + +neat: + # compilation the programs + @cd neatcc && $(MAKE) OUT=$(OUT) + @cd neatld && $(MAKE) OUT=$(OUT) + @cd neatlibc && $(MAKE) OUT=$(OUT) CC=../neatcc/ncc + @cd neatrun && $(MAKE) OUT=$(OUT) NCC=../_ncc NLD=../_nld NLC=../neatlibc + # bootstrapping + @cp neatcc/ncc _ncc + @cp neatld/nld _nld + @cp neatrun/neatcc _neatcc + @cd neatcc && $(MAKE) OUT=$(OUT) CC=../_neatcc clean all + @cd neatlibc && $(MAKE) OUT=$(OUT) CC=../neatcc/ncc clean all + @cd neatld && $(MAKE) OUT=$(OUT) CC=../_neatcc clean all + # setting up neatrun/neatcc + @cd neatrun && $(MAKE) OUT=$(OUT) CC=../_neatcc NCC=$(BASE)/neatcc/ncc \ + NLD=$(BASE)/neatld/nld NLC=$(BASE)/neatlibc clean all + @rm _ncc _nld _neatcc + # compiling the rest + @cd neatas && $(MAKE) CC=../neatrun/neatcc OUT=$(OUT) + @cd neatdbg && $(MAKE) CC=../neatrun/neatcc OUT=$(OUT) + +clean: + @cd neatcc && $(MAKE) clean + @cd neatlibc && $(MAKE) clean + @cd neatas && $(MAKE) clean + @cd neatld && $(MAKE) clean + @cd neatrun && $(MAKE) clean + @cd neatdbg && $(MAKE) clean diff --git a/demo/Makefile b/demo/Makefile new file mode 100644 index 0000000..c685d3e --- /dev/null +++ b/demo/Makefile @@ -0,0 +1,13 @@ +CC = ../neatrun/neatcc + +CFLAGS = -Wall -O2 +LDFLAGS = + +all: test + +%.o: %.c + $(CC) -c $(CFLAGS) $< +test: test.o + $(CC) -o $@ test.o $(LDFLAGS) +clean: + rm -f *.o test diff --git a/demo/test.c b/demo/test.c new file mode 100644 index 0000000..1434f98 --- /dev/null +++ b/demo/test.c @@ -0,0 +1,7 @@ +#include + +int main(void) +{ + printf("NEATCC!\n"); + return 0; +} diff --git a/neatdbg/Makefile b/neatdbg/Makefile new file mode 100644 index 0000000..1dacdb3 --- /dev/null +++ b/neatdbg/Makefile @@ -0,0 +1,13 @@ +CC = neatcc +CFLAGS = -O2 -Wall +LDFLAGS = + +all: elfloc +%.o: %.c + $(CC) -c $(CFLAGS) $< +elfloc: elfloc.o + $(CC) $(LDFLAGS) -o $@ $^ +coredump: coredump.o + $(CC) $(LDFLAGS) -o $@ $^ +clean: + rm -f *.o elfloc coredump diff --git a/neatdbg/coredump.c b/neatdbg/coredump.c new file mode 100644 index 0000000..ec829d3 --- /dev/null +++ b/neatdbg/coredump.c @@ -0,0 +1,119 @@ +/* + * a simple elf core file backtrace viewer + * + * Copyright (C) 2010-2013 Ali Gholami Rudi + * + * This program is released under the Modified BSD license. + */ +#include +#include +#include +#include +#include +#include +#include +#include "elfcore.h" + +/* simplified elf struct and macro names */ +#ifdef __x86_64__ +# define Elf_Phdr Elf64_Phdr +# define Elf_Ehdr Elf64_Ehdr +#else +# define Elf_Phdr Elf32_Phdr +# define Elf_Ehdr Elf32_Ehdr +#endif + +#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1) +#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask)) + +static long readlong(char *mem, unsigned long addr) +{ + Elf_Ehdr *ehdr = (void *) mem; + Elf_Phdr *phdr = (void *) (mem + ehdr->e_phoff); + int i; + for (i = 0; i < ehdr->e_phnum; i++) { + unsigned long beg = phdr[i].p_vaddr; + if (addr >= beg && addr < beg + phdr[i].p_filesz) { + unsigned long diff = addr - beg; + return *(long *) (mem + phdr[i].p_offset + diff); + } + } + return 0; +} + +static void dump_prstatus(char *mem, struct elf_prstatus *prs) +{ + struct user_regs_struct *regs = (void *) &prs->pr_reg; + unsigned long bp = regs->bp; + printf("ip=%lx, sp=%lx, bp=%lx\n\n", regs->ip, regs->sp, regs->bp); + printf("\t%lx: %lx\n", regs->ip, regs->bp); + while (bp) { + printf("\t%lx: %lx\n", + readlong(mem, bp + sizeof(long)), readlong(mem, bp)); + bp = readlong(mem, bp); + } + printf("\n"); +} + +struct elfnote { + int namesz; + int descsz; + int type; +}; + +static void dumpnote(char *mem, char *note, int len) +{ + struct elfnote *elfnote; + char *end = note + len; + while (note < end) { + elfnote = (void *) note; + note += sizeof(*elfnote); + note += ALIGN(elfnote->namesz, 4); + if (elfnote->type == NT_PRSTATUS) + dump_prstatus(mem, (void *) note); + note += ALIGN(elfnote->descsz, 4); + } +} + +static void dumpelf(char *mem) +{ + Elf_Ehdr *ehdr = (void *) mem; + Elf_Phdr *phdr = (void *) (mem + ehdr->e_phoff); + if (ehdr->e_type == ET_CORE && phdr[0].p_type == PT_NOTE) + dumpnote(mem, mem + phdr[0].p_offset, phdr[0].p_filesz); +} + +static void die(char *msg) +{ + perror(msg); + exit(1); +} + +static long filesize(int fd) +{ + struct stat stat; + fstat(fd, &stat); + return stat.st_size; +} + +int main(int argc, char **argv) +{ + int fd; + long size; + void *mem; + if (argc < 2) { + printf("Usage: %s path\n", argv[0]); + return 0; + } + fd = open(argv[1], O_RDONLY); + if (fd == -1) + die("open"); + size = filesize(fd); + mem = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + if (!mem) + die("mmap"); + dumpelf(mem); + munmap(mem, size); + close(fd); + return 0; +} diff --git a/neatdbg/elfloc.c b/neatdbg/elfloc.c new file mode 100644 index 0000000..27d6378 --- /dev/null +++ b/neatdbg/elfloc.c @@ -0,0 +1,183 @@ +/* + * elfloc, find elf symbols around a virtual address + * + * Copyright (C) 2010-2013 Ali Gholami Rudi + * + * This program is released under the Modified BSD license. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +/* simplified elf struct and macro names */ +#ifdef __x86_64__ +# define Elf_Phdr Elf64_Phdr +# define Elf_Ehdr Elf64_Ehdr +# define Elf_Shdr Elf64_Shdr +# define Elf_Sym Elf64_Sym +#else +# define Elf_Phdr Elf32_Phdr +# define Elf_Ehdr Elf32_Ehdr +# define Elf_Shdr Elf32_Shdr +# define Elf_Sym Elf32_Sym +#endif + +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +static long filesize(int fd) +{ + struct stat stat; + fstat(fd, &stat); + return stat.st_size; +} + +static char *fileread(char *path) +{ + int fd = open(path, O_RDONLY); + int size = filesize(fd); + char *buf = malloc(size); + read(fd, buf, size); + close(fd); + return buf; +} + +static long htol(char *t) +{ + long n = 0; + while (*t && isalnum(*t)) { + n <<= 4; + if (*t >= '0' && *t <= '9') + n |= *t - '0'; + if (*t >= 'a' && *t <= 'f') + n |= *t - 'a' + 10; + t++; + } + return n; +} + +static Elf_Ehdr *ehdr; +static Elf_Phdr *phdr; +static Elf_Shdr *shdr; +static Elf_Sym *syms; +static int nsyms; +static char *symstr; + +static void init_data(void *mem) +{ + int i; + ehdr = mem; + shdr = ehdr->e_shnum ? mem + ehdr->e_shoff : NULL; + phdr = ehdr->e_phnum ? mem + ehdr->e_phoff : NULL; + + for (i = 0; i < ehdr->e_shnum; i++) { + if (shdr[i].sh_type == SHT_SYMTAB) { + syms = mem + shdr[i].sh_offset; + nsyms = shdr[i].sh_size / sizeof(syms[0]); + symstr = mem + shdr[shdr[i].sh_link].sh_offset; + } + } +} + +static int mem_to_off(unsigned long vaddr) +{ + int i; + for (i = 0; i < ehdr->e_phnum; i++) { + unsigned long base = phdr[i].p_vaddr; + if (vaddr >= base && vaddr <= base + phdr[i].p_memsz) + return phdr[i].p_offset + MIN(phdr[i].p_filesz, + vaddr - base); + } + return 0; +} + +static int sym_to_mem(Elf_Sym *sym) +{ + if (sym->st_shndx == SHN_UNDEF || sym->st_shndx == SHN_COMMON) + return 0; + return sym->st_value; +} + +static Elf_Sym *get_sym(char *name) +{ + int i; + for (i = 0; i < nsyms; i++) + if (!strcmp(name, symstr + syms[i].st_name) && + syms[i].st_shndx != SHN_UNDEF) + return &syms[i]; + return NULL; +} + +static int sec_region(unsigned long vaddr, unsigned long *beg, unsigned long *end) +{ + int i; + for (i = 0; i < ehdr->e_phnum; i++) { + unsigned long base = phdr[i].p_vaddr; + if (vaddr >= base && vaddr < base + phdr[i].p_memsz) { + *beg = base; + *end = base + phdr[i].p_filesz; + return 0; + } + } + return 1; +} + +static void boundaries(unsigned long vaddr) +{ + char *beg_sym = NULL; + char *end_sym = NULL; + unsigned long beg = 0l; + unsigned long end = -1l; + int i; + sec_region(vaddr, &beg, &end); + for (i = 0; i < nsyms; i++) { + unsigned long symaddr = sym_to_mem(&syms[i]); + char *name = symstr + syms[i].st_name; + if (!symaddr || !*name) + continue; + if (symaddr <= vaddr && symaddr >= beg) { + beg_sym = name; + beg = symaddr; + } + if (symaddr > vaddr && symaddr <= end) { + end_sym = name; + end = symaddr; + } + } + printf("%s\t+%lx\t%lx\t%d\n", + beg_sym ? beg_sym : "NULL", + vaddr - beg, beg, mem_to_off(beg)); + printf("%s\t-%lx\t%lx\t%d\n", + end_sym ? end_sym : "NULL", + end - vaddr, end, mem_to_off(end)); +} + +int main(int argc, char **argv) +{ + unsigned long addr; + char *name; + char *buf; + if (argc < 3) { + printf("usage: %s addr elf\n", argv[0]); + return 1; + } + buf = fileread(argv[argc - 1]); + init_data(buf); + name = argv[1]; + if (name[0] == '=') { + Elf_Sym *sym = get_sym(name + 1); + if (!sym) + return 1; + addr = sym_to_mem(sym); + } else { + addr = htol(argv[1]); + } + if (syms) + boundaries(addr); + free(buf); + return 0; +} diff --git a/neatrun/Makefile b/neatrun/Makefile new file mode 100644 index 0000000..581fad1 --- /dev/null +++ b/neatrun/Makefile @@ -0,0 +1,16 @@ +NCC = "/path/to/neatcc/ncc" +NLD = "/path/to/neatld/nld" +NLC = "/path/to/neatlibc/" + +CC = cc +CFLAGS = -DNCC=\"$(NCC)\" -DNLD=\"$(NLD)\" -DNLC=\"$(NLC)\" +LDFLAGS = + +all: neatcc + +%.o: %.c + $(CC) $(CFLAGS) -c $^ +neatcc: neatcc.o + $(CC) -o $@ neatcc.o $(LDFLAGS) +clean: + rm -f *.o neatcc diff --git a/neatrun/neatcc.c b/neatrun/neatcc.c new file mode 100644 index 0000000..10ac11b --- /dev/null +++ b/neatrun/neatcc.c @@ -0,0 +1,43 @@ +#include +#include +#include + +#define MAXARGS 512 + +static void die(char *msg) +{ + write(2, msg, strlen(msg)); + exit(1); +} + +int main(int argc, char *argv[], char *envp[]) +{ + char *targv[MAXARGS]; + int targc = 0; + int cc = 0; + int i; + if (argc < 2) + die("neatcc: ncc/nld wrapper\n"); + for (i = 1; i < argc; i++) + if (argv[i][0] == '-' && argv[i][1] == 'c') + cc = 1; + if (cc) { + targv[targc++] = NCC; + targv[targc++] = "-Dfloat=long"; + targv[targc++] = "-Ddouble=long"; + targv[targc++] = "-D__extension__="; + targv[targc++] = "-I" NLC; + for (i = 1; i < argc; i++) + targv[targc++] = argv[i]; + } else { + targv[targc++] = NLD; + for (i = 1; i < argc; i++) + targv[targc++] = argv[i]; + targv[targc++] = NLC "/start.o"; + targv[targc++] = NLC "/libc.a"; + } + targv[targc] = NULL; + execve(targv[0], targv, envp); + die("neatcc: could not find ncc/nld\n"); + return 1; +} -- 2.11.4.GIT