feat(tools): fas2dump: generate elf file with symbol table from .fas
This commit is contained in:
		
							parent
							
								
									ca6e6e9487
								
							
						
					
					
						commit
						81abea70fd
					
				
					 12 changed files with 1320 additions and 25 deletions
				
			
		
							
								
								
									
										3
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -33,6 +33,9 @@ bochsrc.bxrc | |||
| *.EFI | ||||
| *.fd | ||||
| *.mod | ||||
| *.fas | ||||
| *.sym | ||||
| *.dbg | ||||
| webring.json | ||||
| webring.txt | ||||
| kernel/const.inc | ||||
|  |  | |||
							
								
								
									
										39
									
								
								bin/fas2sym/buffer.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								bin/fas2sym/buffer.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,39 @@ | |||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include "fas2sym.h" | ||||
| 
 | ||||
| int | ||||
| buffer_put(struct buffer *buff, const uint8_t *data, size_t size, | ||||
| 		   size_t *index) | ||||
| { | ||||
| 	if (index != NULL) | ||||
| 	{ | ||||
| 		*index = buff->cnt; | ||||
| 	} | ||||
| 
 | ||||
| 	while (buff->cap < buff->cnt + size) | ||||
| 	{ | ||||
| 		buff->cap = (buff->cap == 0 ? 32 : buff->cap * 2); | ||||
| 		buff->data = (uint8_t *)realloc(buff->data, buff->cap); | ||||
| 		if (buff->data == NULL) | ||||
| 		{ | ||||
| 			msg_err(NULL); | ||||
| 			return (-1); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	memcpy(buff->data + buff->cnt, data, size); | ||||
| 	buff->cnt += size; | ||||
| 
 | ||||
| 	return (0); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| buffer_cleanup(struct buffer *buff) | ||||
| { | ||||
| 	buff->cnt = 0; | ||||
| 	buff->cap = 0; | ||||
| 	free(buff->data); | ||||
| 	buff->data = 0; | ||||
| } | ||||
							
								
								
									
										216
									
								
								bin/fas2sym/elf.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										216
									
								
								bin/fas2sym/elf.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,216 @@ | |||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <elf.h> | ||||
| #include "fas2sym.h" | ||||
| 
 | ||||
| enum sections { | ||||
| 	SEC_NULL   = 0, | ||||
| 	SEC_SHSTRTAB, | ||||
| 	SEC_STRTAB, | ||||
| 	SEC_SYMTAB, | ||||
| 	SEC_END | ||||
| }; | ||||
| 
 | ||||
| static Elf32_Ehdr elf_ehdr = { | ||||
| 	{ | ||||
| 		ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, | ||||
| 		ELFCLASS32, ELFDATA2LSB, EV_CURRENT, | ||||
| 		0, 0, 0, 0, 0, 0, 0, 0, 0 | ||||
| 	}, | ||||
| 	ET_REL, EM_386, EV_CURRENT, 0, 0, 0, 0, | ||||
|     sizeof(Elf32_Ehdr), sizeof(Elf32_Phdr), 0, | ||||
| 	sizeof(Elf32_Shdr), SEC_END, SEC_SHSTRTAB | ||||
| }; | ||||
| 
 | ||||
| static Elf32_Shdr elf_shdrs[SEC_END] = { | ||||
| 	{ 0, SHT_NULL, 0, 0, 0, 0, SHN_UNDEF, 0, 0, 0 }, | ||||
| 	/* .shstrtab */ | ||||
| 	{ 1, SHT_STRTAB, 0, 0, 0, 0, SHN_UNDEF, 0, 1, 0 }, | ||||
| 	/* .strtab */ | ||||
| 	{ 11, SHT_STRTAB, 0, 0, 0, 0, SHN_UNDEF, 0, 1, 0 }, | ||||
| 	/* .symtab */ | ||||
| 	{ | ||||
| 		19, SHT_SYMTAB, 0, 0, 0, 0, | ||||
| 		SEC_STRTAB, 0, 4, sizeof(Elf32_Sym) | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| static struct buffer elf_shstrtab = { 0, 0, NULL }; | ||||
| static struct buffer elf_strtab = { 0, 0, NULL }; | ||||
| static struct buffer elf_symtab = { 0, 0, NULL }; | ||||
| 
 | ||||
| static int | ||||
| elf_shstrtab_init(void) | ||||
| { | ||||
| 	const uint8_t initial[] = "\0.shstrtab\0.strtab\0.symtab\0"; | ||||
| 
 | ||||
| 	return (buffer_put(&elf_shstrtab, initial, sizeof(initial), NULL)); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| elf_strtab_init(void) | ||||
| { | ||||
| 	const uint8_t initial[] = "\0"; | ||||
| 
 | ||||
| 	return (buffer_put(&elf_strtab, initial, sizeof(initial), NULL)); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| elf_symtab_init(void) | ||||
| { | ||||
| 	const Elf32_Sym initial = { 0, 0, 0, 0, 0, SHN_UNDEF }; | ||||
| 
 | ||||
| 	return (buffer_put(&elf_symtab, (uint8_t *)&initial, | ||||
| 					   sizeof(Elf32_Sym), NULL)); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| elf_init(void) | ||||
| { | ||||
| 	if (elf_shstrtab_init() != 0) | ||||
| 	{ | ||||
| 		return (-1); | ||||
| 	} | ||||
| 
 | ||||
| 	if (elf_strtab_init() != 0) | ||||
| 	{ | ||||
| 		return (-1); | ||||
| 	} | ||||
| 
 | ||||
| 	if (elf_symtab_init() != 0) | ||||
| 	{ | ||||
| 		return (-1); | ||||
| 	} | ||||
| 
 | ||||
| 	return (0); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| elf_add_symbol(uint32_t name_off, uint32_t value, uint32_t size, | ||||
| 			   uint8_t info, uint16_t sect) | ||||
| { | ||||
| 	Elf32_Sym sym = { 0 }; | ||||
| 
 | ||||
| 	sym.st_name = name_off; | ||||
| 	sym.st_value = value; | ||||
| 	sym.st_size = size; | ||||
| 	sym.st_info = info; | ||||
| 	sym.st_shndx = sect; | ||||
| 
 | ||||
| 	msg_verbose(2, "add symbol: %s", | ||||
| 				(char *)(elf_strtab.data + name_off)); | ||||
| 
 | ||||
| 	return (buffer_put(&elf_symtab, (uint8_t *)&sym, | ||||
| 					   sizeof(Elf32_Sym), NULL)); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| elf_add_str(const char *str, size_t len, size_t *idx) | ||||
| { | ||||
| 	return (buffer_put(&elf_strtab, (uint8_t *)str, len, idx)); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| elf_write_tab(struct buffer *buff, FILE *fp) | ||||
| { | ||||
| 	if (buff->cnt == 0 || buff->data == NULL) | ||||
| 	{ | ||||
| 		return (0); | ||||
| 	} | ||||
| 
 | ||||
| 	if (fwrite(buff->data, buff->cnt, 1, fp) != 1) | ||||
| 	{ | ||||
| 		return (-1); | ||||
| 	} | ||||
| 
 | ||||
| 	return (0); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| elf_compute_section_offsets(void) | ||||
| { | ||||
| 	size_t offset; | ||||
| 
 | ||||
| 	offset = sizeof(Elf32_Ehdr); | ||||
| 	elf_shdrs[SEC_SHSTRTAB].sh_offset = offset; | ||||
| 	elf_shdrs[SEC_SHSTRTAB].sh_size = elf_shstrtab.cnt; | ||||
| 
 | ||||
| 	offset += elf_shstrtab.cnt; | ||||
| 
 | ||||
| 	elf_shdrs[SEC_STRTAB].sh_offset = offset; | ||||
| 	elf_shdrs[SEC_STRTAB].sh_size = elf_strtab.cnt; | ||||
| 
 | ||||
| 	offset += elf_strtab.cnt; | ||||
| 
 | ||||
| 	elf_shdrs[SEC_SYMTAB].sh_offset = offset; | ||||
| 	elf_shdrs[SEC_SYMTAB].sh_size = elf_symtab.cnt; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| elf_write(const char *file) | ||||
| { | ||||
| 	FILE *fp; | ||||
| 	int status; | ||||
| 	size_t offset; | ||||
| 
 | ||||
| 	fp = fopen(file, "wb"); | ||||
| 	if (fp == NULL) | ||||
| 	{ | ||||
| 	    msg_err(file); | ||||
| 		return (-1); | ||||
| 	} | ||||
| 
 | ||||
| 	status = -1; | ||||
| 
 | ||||
| 	/* compute section headers offset */ | ||||
| 	elf_ehdr.e_shoff = sizeof(Elf32_Ehdr); | ||||
| 	elf_ehdr.e_shoff += elf_shstrtab.cnt +  elf_strtab.cnt; | ||||
| 	elf_ehdr.e_shoff += elf_symtab.cnt; | ||||
| 
 | ||||
| 	if (fwrite(&elf_ehdr, sizeof(Elf32_Ehdr), 1, fp) != 1) | ||||
| 	{ | ||||
| 		msg_errx("%s: An error occurred while writting elf header", file); | ||||
| 		goto end; | ||||
| 	} | ||||
| 
 | ||||
| 	if (elf_write_tab(&elf_shstrtab, fp) != 0) | ||||
| 	{ | ||||
| 		msg_errx("%s: An error occured while writting .shstrtab data", file); | ||||
| 		goto end; | ||||
| 	} | ||||
| 	if (elf_write_tab(&elf_strtab, fp) != 0) | ||||
| 	{ | ||||
| 		msg_errx("%s: An error occured while writting .strtab data", file); | ||||
| 		goto end; | ||||
| 	} | ||||
| 
 | ||||
| 	if (elf_write_tab(&elf_symtab, fp) != 0) | ||||
| 	{ | ||||
| 		msg_errx("%s: An error occured while writting .symtab data", file); | ||||
| 		goto end; | ||||
| 	} | ||||
| 
 | ||||
| 	/* section headers */ | ||||
| 	elf_compute_section_offsets(); | ||||
| 	/* XXX: fix me */ | ||||
| 	elf_shdrs[SEC_SYMTAB].sh_info = 0; /* (elf_symtab.cnt / sizeof(Elf32_Sym)) + 1;*/ | ||||
| 
 | ||||
| 	if (fwrite(elf_shdrs, sizeof(Elf32_Shdr), SEC_END, fp) != SEC_END) | ||||
| 	{ | ||||
| 		msg_errx("%s: An error occured while writting sections headers", file); | ||||
| 		goto end; | ||||
| 	} | ||||
| 
 | ||||
| 	status = 0; | ||||
| end: | ||||
| 	fclose(fp); | ||||
| 	return (status); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| elf_cleanup(void) | ||||
| { | ||||
| 	buffer_cleanup(&elf_shstrtab); | ||||
| 	buffer_cleanup(&elf_strtab); | ||||
| 	buffer_cleanup(&elf_symtab); | ||||
| } | ||||
							
								
								
									
										192
									
								
								bin/fas2sym/fas.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										192
									
								
								bin/fas2sym/fas.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,192 @@ | |||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <inttypes.h> | ||||
| #include <string.h> | ||||
| #include <fas.h> | ||||
| #include <elf.h> | ||||
| #include "fas2sym.h" | ||||
| 
 | ||||
| static FAS_Hdr fas_hdr; | ||||
| static char *fas_strtab = NULL; | ||||
| static FAS_Sym *fas_symtab = NULL; | ||||
| static uint8_t *fas_psrc = NULL; | ||||
| static size_t fas_sym_cnt = 0; | ||||
| 
 | ||||
| static void | ||||
| pstr2cstr(char *dst, const uint8_t *src) | ||||
| { | ||||
| 	size_t psz; | ||||
| 
 | ||||
| 	psz = *src++; | ||||
|     while (psz > 0) | ||||
| 	{ | ||||
| 		*dst++ = *src++; | ||||
| 		psz--; | ||||
| 	} | ||||
| 
 | ||||
| 	*dst = '\0'; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| fas_load_table(uint8_t **dest, size_t offset, size_t size, FILE *fp) | ||||
| { | ||||
| 	if (size == 0) | ||||
| 	{ | ||||
| 		return (0); /* XXX */ | ||||
| 	} | ||||
| 
 | ||||
| 	*dest = (uint8_t *)malloc(size); | ||||
| 	if (*dest == NULL) | ||||
| 	{ | ||||
| 		msg_err(NULL); | ||||
| 		return (-1); | ||||
| 	} | ||||
| 
 | ||||
| 	if (fseek(fp, offset, SEEK_SET) != 0) | ||||
| 	{ | ||||
| 		msg_err(NULL); | ||||
| 		return (-1); | ||||
| 	} | ||||
| 
 | ||||
| 	if (fread(*dest, size, 1, fp) != 1) | ||||
| 	{ | ||||
| 		msg_errx("An unexpected error/eof occured while reading"); | ||||
| 		return (-1); | ||||
| 	} | ||||
| 
 | ||||
| 	return (0); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| fas_load_file(const char *file) | ||||
| { | ||||
| 	FILE *fp; | ||||
| 
 | ||||
| 	fp = fopen(file, "rb"); | ||||
| 	if (fp == NULL) | ||||
| 	{ | ||||
| 		msg_err(file); | ||||
| 		return (-1); | ||||
| 	} | ||||
| 
 | ||||
| 	if (fread(&fas_hdr, sizeof(FAS_Hdr), 1, fp) != 1) | ||||
| 	{ | ||||
| 		msg_errx("%s: unexpected error/eof while reading FAS header", | ||||
| 				 file); | ||||
| 		goto err; | ||||
| 	} | ||||
| 
 | ||||
| 	if (fas_hdr.magic != FAS_MAGIC) | ||||
| 	{ | ||||
| 		msg_errx("%s: invalid magic, got '%08" PRIX32 | ||||
| 				 "' instead of '%08" PRIX32 "'", | ||||
| 				 file, (uint32_t)FAS_MAGIC); | ||||
| 		goto err; | ||||
| 	} | ||||
| 
 | ||||
| 	if (fas_load_table((uint8_t **)&fas_strtab, fas_hdr.strtab_off, | ||||
| 					   fas_hdr.strtab_len, fp) != 0) | ||||
| 	{ | ||||
| 		msg_errx("%s: can't load string table", file); | ||||
| 		goto err_cleanup; | ||||
| 	} | ||||
| 
 | ||||
| 	if (fas_load_table((uint8_t **)&fas_symtab, fas_hdr.symtab_off, | ||||
| 					   fas_hdr.symtab_len, fp) != 0) | ||||
| 	{ | ||||
| 		msg_errx("%s: can't load symbol table", file); | ||||
| 		goto err_cleanup; | ||||
| 	} | ||||
| 
 | ||||
| 	if (fas_load_table(&fas_psrc, fas_hdr.psrc_off, fas_hdr.psrc_len, | ||||
| 					   fp) != 0) | ||||
| 	{ | ||||
| 	    msg_errx("%s: can't load preprocessed sources", file); | ||||
| 		goto err_cleanup; | ||||
| 	} | ||||
| 
 | ||||
| 	fas_sym_cnt = fas_hdr.symtab_len / sizeof(FAS_Sym); | ||||
| 
 | ||||
| 	msg_verbose(1, "%zu symbol(s) loaded from %s", fas_sym_cnt, file); | ||||
| 
 | ||||
| 	fclose(fp); | ||||
| 	return (0); | ||||
| 
 | ||||
| err_cleanup: | ||||
| 	fas_cleanup(); | ||||
| err: | ||||
| 	fclose(fp); | ||||
| 	return (-1); | ||||
| } | ||||
| 
 | ||||
| static uint32_t | ||||
| fas_export_symbol_name(uint32_t name_off) | ||||
| { | ||||
| 	size_t idx = 0; | ||||
| 	char *ptr; | ||||
| 	char name[256] = { 0 }; | ||||
| 
 | ||||
| 	if (name_off == 0) | ||||
| 	{ | ||||
| 		return (0); /* anonymous symbol */ | ||||
| 	} | ||||
| 
 | ||||
| 	if (name_off & (1<<31)) /* if in fas strtab */ | ||||
| 	{ | ||||
| 		ptr = fas_strtab + (name_off & ~(1<<31)); /* XXX */ | ||||
| 	} | ||||
| 	else /* otherwhise it's in psrc */ | ||||
| 	{ | ||||
| 		pstr2cstr(name, fas_psrc + name_off); | ||||
| 		ptr = name; | ||||
| 	} | ||||
| 
 | ||||
| 	if (elf_add_str(ptr, strlen(ptr) + 1, &idx) != 0) | ||||
| 	{ | ||||
| 		/* error occured */ | ||||
| 		return (0); | ||||
| 	} | ||||
| 
 | ||||
| 	return (idx); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| fas_export_symbols(void) | ||||
| { | ||||
| 	size_t idx; | ||||
| 	char *name_ptr; | ||||
|     size_t name_idx; | ||||
| 
 | ||||
| 	/* export file name symbol */ | ||||
| 	name_ptr = fas_strtab + fas_hdr.ifnm_off; | ||||
| 	elf_add_str(name_ptr, strlen(name_ptr) + 1, &name_idx); | ||||
| 	elf_add_symbol(name_idx, 0, 0, ELF32_ST_INFO(STB_LOCAL, STT_FILE), | ||||
| 				   SHN_ABS); | ||||
| 
 | ||||
| 	/* export other symbol */ | ||||
| 	for (idx = 0; idx < fas_sym_cnt; idx++) | ||||
| 	{ | ||||
| 		if ((fas_symtab[idx].flags & FAS_SYM_DEF) == 0 || | ||||
| 			fas_symtab[idx].flags & FAS_SYM_ASM_TIME) | ||||
| 		{ | ||||
| 			continue; | ||||
| 		} | ||||
| 
 | ||||
| 		name_idx = fas_export_symbol_name(fas_symtab[idx].name_off); | ||||
| 
 | ||||
| 		elf_add_symbol(name_idx, fas_symtab[idx].value, 0, | ||||
| 					   ELF32_ST_INFO(STB_LOCAL, STT_OBJECT), SHN_ABS); | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| void | ||||
| fas_cleanup(void) | ||||
| { | ||||
| 	free(fas_psrc); | ||||
| 	fas_psrc = NULL; | ||||
| 	free(fas_symtab); | ||||
| 	fas_symtab = NULL; | ||||
| 	free(fas_strtab); | ||||
| 	fas_strtab = NULL; | ||||
| } | ||||
							
								
								
									
										37
									
								
								bin/fas2sym/fas2sym.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								bin/fas2sym/fas2sym.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,37 @@ | |||
| #ifndef FAS2SYM_H | ||||
| # define FAS2SYM_H 1 | ||||
| 
 | ||||
| # include <stddef.h> | ||||
| # include <stdint.h> | ||||
| # include <stdarg.h> | ||||
| 
 | ||||
| struct buffer { | ||||
| 	size_t cap; | ||||
| 	size_t cnt; | ||||
| 	uint8_t *data; | ||||
| }; | ||||
| 
 | ||||
| /* buffer.c */ | ||||
| int buffer_put(struct buffer *buff, const uint8_t *data, | ||||
| 			   size_t size, size_t *index); | ||||
| void buffer_cleanup(struct buffer *buff); | ||||
| 
 | ||||
| /* fas.c */ | ||||
| int fas_load_file(const char *file); | ||||
| void fas_export_symbols(void); | ||||
| void fas_cleanup(void); | ||||
| 
 | ||||
| /* elf.c */ | ||||
| int elf_init(void); | ||||
| int elf_add_str(const char *str, size_t len, size_t *idx); | ||||
| int elf_add_symbol(uint32_t name_off, uint32_t value, uint32_t size, | ||||
| 				   uint8_t info, uint16_t sect); | ||||
| int elf_write(const char *file); | ||||
| void elf_cleanup(void); | ||||
| 
 | ||||
| /* main.c */ | ||||
| void msg_err(const char *fmt, ...); | ||||
| void msg_errx(const char *fmt, ...); | ||||
| void msg_verbose(int level, const char *fmt, ...); | ||||
| 
 | ||||
| #endif /* !FAS2SYM_H */ | ||||
							
								
								
									
										152
									
								
								bin/fas2sym/main.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										152
									
								
								bin/fas2sym/main.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,152 @@ | |||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <stdarg.h> | ||||
| #include <string.h> | ||||
| #include <unistd.h> | ||||
| #include <libgen.h> | ||||
| #include "fas2sym.h" | ||||
| 
 | ||||
| static const char *prg_name; | ||||
| static const char *outfile = "out.sym"; | ||||
| static int verbose = 0; | ||||
| 
 | ||||
| static void | ||||
| msg_err_common(const char *fmt, va_list ap) | ||||
| { | ||||
| 	fprintf(stderr, "%s: ", prg_name); | ||||
| 	if (fmt) | ||||
| 	{ | ||||
| 		vfprintf(stderr, fmt, ap); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void | ||||
| msg_errx(const char *fmt, ...) | ||||
| { | ||||
| 	va_list ap; | ||||
| 
 | ||||
| 	va_start(ap, fmt); | ||||
| 
 | ||||
| 	msg_err_common(fmt, ap); | ||||
| 	fprintf(stderr, "\n"); | ||||
| 
 | ||||
| 	va_end(ap); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| msg_err(const char *fmt, ...) | ||||
| { | ||||
| 	va_list ap; | ||||
| 
 | ||||
| 	va_start(ap, fmt); | ||||
| 
 | ||||
| 	msg_err_common(fmt, ap); | ||||
| 	if (fmt) | ||||
| 	{ | ||||
| 		fprintf(stderr, ": "); | ||||
| 	} | ||||
| 
 | ||||
| 	fprintf(stderr, "%s\n", strerror(errno)); | ||||
| 
 | ||||
| 	va_end(ap); | ||||
| } | ||||
| 
 | ||||
| void | ||||
| msg_verbose(int level, const char *fmt, ...) | ||||
| { | ||||
| 	va_list ap; | ||||
| 
 | ||||
| 	va_start(ap, fmt); | ||||
| 	if (level <= verbose) | ||||
| 	{ | ||||
| 		vprintf(fmt, ap); | ||||
| 		printf("\n"); | ||||
| 	} | ||||
| 	va_end(ap); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| usage(int retval) | ||||
| { | ||||
| 	if (retval == EXIT_FAILURE) | ||||
| 	{ | ||||
| 		fprintf(stderr, "Try '%s -h' for more information.\n", | ||||
| 				prg_name); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		printf("Usage: %s [-o OUTPUT] file\n", prg_name); | ||||
| 	} | ||||
| 
 | ||||
| 	exit(retval); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| version(void) | ||||
| { | ||||
| 	printf("%s (%s) %s\n", prg_name, MK_PACKAGE, MK_COMMIT); | ||||
| 
 | ||||
| 	exit(EXIT_SUCCESS); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| main(int argc, char **argv) | ||||
| { | ||||
| 	int c; | ||||
| 	int status; | ||||
| 
 | ||||
| 	prg_name = basename(argv[0]); | ||||
| 
 | ||||
| 	while ((c = getopt(argc, argv, "hvVo:")) != -1) | ||||
| 	{ | ||||
| 		switch (c) | ||||
| 		{ | ||||
| 		case 'h': | ||||
| 			usage(EXIT_SUCCESS); | ||||
| 			break; | ||||
| 		case 'V': | ||||
| 			version(); | ||||
| 			break; | ||||
| 		case 'v': | ||||
| 			verbose++; | ||||
| 			break; | ||||
| 		case 'o': | ||||
| 			outfile = optarg; | ||||
| 			break; | ||||
| 		default: | ||||
| 			usage(EXIT_FAILURE); | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (optind >= argc) | ||||
| 	{ | ||||
| 		usage(EXIT_FAILURE); | ||||
| 	} | ||||
| 
 | ||||
| 	if (fas_load_file(argv[optind]) != 0) | ||||
| 	{ | ||||
| 		return (EXIT_FAILURE); | ||||
| 	} | ||||
| 
 | ||||
| 	status = EXIT_FAILURE; | ||||
| 
 | ||||
| 	if (elf_init() != 0) | ||||
| 	{ | ||||
| 		goto cleanup; | ||||
| 	} | ||||
| 
 | ||||
| 	fas_export_symbols(); | ||||
| 
 | ||||
| 	if (elf_write(outfile) != 0) | ||||
| 	{ | ||||
| 		goto cleanup; | ||||
| 	} | ||||
| 
 | ||||
| 	status = EXIT_SUCCESS; | ||||
| cleanup: | ||||
| 	elf_cleanup(); | ||||
| 	fas_cleanup(); | ||||
| 
 | ||||
| 	return (status); | ||||
| } | ||||
							
								
								
									
										338
									
								
								bin/fasdump/main.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										338
									
								
								bin/fasdump/main.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,338 @@ | |||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <inttypes.h> | ||||
| #include <fas.h> | ||||
| 
 | ||||
| struct buff { | ||||
| 	size_t size; | ||||
| 	uint8_t *data; | ||||
| }; | ||||
| 
 | ||||
| static char *prg_name = "fasdump"; | ||||
| static struct fas_header hdr; | ||||
| static struct buff strtab = { 0, NULL }; | ||||
| static struct buff symtab = { 0, NULL }; | ||||
| static struct buff psrc = { 0, NULL }; | ||||
| static struct buff asmdmp = { 0, NULL }; | ||||
| static struct buff sectab = { 0, NULL }; | ||||
| static struct buff symref = { 0, NULL }; | ||||
| 
 | ||||
| static void | ||||
| version(void) | ||||
| { | ||||
| 	printf("%s (%s) %s\n", prg_name, MK_PACKAGE, MK_COMMIT); | ||||
| 	exit(EXIT_SUCCESS); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| usage(int retval) | ||||
| { | ||||
| 	if (retval == EXIT_FAILURE) | ||||
| 	{ | ||||
| 		fprintf(stderr, "Try '%s -h' for more informations.", prg_name); | ||||
| 	} | ||||
| 
 | ||||
| 	exit(retval); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| readall(uint8_t *dest, size_t size, FILE *fp) | ||||
| { | ||||
| 	size_t total; | ||||
| 	size_t byte_read; | ||||
| 
 | ||||
| 	total = 0; | ||||
| 	do | ||||
| 	{ | ||||
| 		byte_read = fread(dest + total, 1, size - total, fp); | ||||
| 		if (byte_read == 0) | ||||
| 		{ | ||||
| 			return (-1); | ||||
| 		} | ||||
| 
 | ||||
| 		total += byte_read; | ||||
| 	} | ||||
| 	while (total < size); | ||||
| 
 | ||||
| 	return (0); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| load_table(struct buff *dst, size_t off, size_t len, FILE *fp) | ||||
| { | ||||
| 	dst->size = len; | ||||
| 	if (len == 0) | ||||
| 	{ | ||||
| 		return (0); | ||||
| 	} | ||||
| 
 | ||||
| 	dst->data = (uint8_t *)malloc(len); | ||||
| 	if (dst->data == NULL) | ||||
| 	{ | ||||
| 		return (-1); | ||||
| 	} | ||||
| 
 | ||||
| 	if (fseek(fp, off, SEEK_SET) != 0) | ||||
| 	{ | ||||
| 		goto clean_up; | ||||
| 	} | ||||
| 
 | ||||
| 	if (readall(dst->data, len, fp) != 0) | ||||
| 	{ | ||||
| 		goto clean_up; | ||||
| 	} | ||||
| 
 | ||||
| 	return (0); | ||||
| 
 | ||||
| clean_up: | ||||
| 	free(dst->data); | ||||
| 	dst->size = 0; | ||||
| 	return (-1); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| read_header(FILE *fp) | ||||
| { | ||||
| 	if (readall((uint8_t *)&hdr, sizeof(struct fas_header), fp) != 0) | ||||
| 	{ | ||||
| 		return (-1); | ||||
| 	} | ||||
| 
 | ||||
| 	if (hdr.magic != FAS_MAGIC) | ||||
| 	{ | ||||
| 		return (-1); | ||||
| 	} | ||||
| 
 | ||||
| 	return (0); | ||||
| } | ||||
| 
 | ||||
| static inline char * | ||||
| strtab_get(size_t off) | ||||
| { | ||||
| 	if (off > strtab.size) | ||||
| 	{ | ||||
| 		return (NULL); | ||||
| 	} | ||||
| 
 | ||||
| 	return (strtab.data + off); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| print_header(void) | ||||
| { | ||||
| 	printf("FAS Header:\n"); | ||||
| 	printf("  Magic:                %X\n", hdr.magic); | ||||
| 	printf("  Fasm version:         %d.%d\n", hdr.ver_major, | ||||
| 		   hdr.ver_minor); | ||||
| 	printf("  Length:               %hu\n", hdr.length); | ||||
| 	printf("  Input file:           %s\n", strtab_get(hdr.ifnm_off)); | ||||
| 	printf("  Output file:          %s\n", strtab_get(hdr.ofnm_off)); | ||||
| 	printf("  String table offset:  0x%08X\n", hdr.strtab_off); | ||||
| 	printf("  String table length:  %u\n", hdr.strtab_len); | ||||
| 	printf("  Symbol table offset:  0x%08X\n", hdr.symtab_off); | ||||
| 	printf("  Symbol table length:  %u\n", hdr.symtab_len); | ||||
| 	printf("  ASM dump offset:      0x%08X\n", hdr.asmdmp_off); | ||||
| 	printf("  ASM dump length:      %d\n", hdr.asmdmp_len); | ||||
| 	printf("  Section table offset: 0x%08X\n", hdr.sectab_off); | ||||
| 	printf("  Section table length: %d\n", hdr.sectab_len); | ||||
| 	printf("  Symref table offset:  0x%08X\n", hdr.symref_off); | ||||
| 	printf("  Symref table length:  %d\n", hdr.symref_len); | ||||
| 
 | ||||
| 	printf("\n"); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| print_sections(void) | ||||
| { | ||||
| 	size_t seccnt; | ||||
| 	size_t idx; | ||||
| 	uint32_t *sec; | ||||
| 
 | ||||
| 	seccnt = sectab.size / sizeof(uint32_t); | ||||
| 	sec = (uint32_t *)sectab.data; | ||||
| 	printf("Section names:\n"); | ||||
| 	for (idx = 0; idx < seccnt; idx++) | ||||
| 	{ | ||||
| 		printf("  %s\n", strtab_get(sec[idx])); | ||||
| 	} | ||||
| 	printf("\n"); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| pstr2cstr(char *dst, const char *src) | ||||
| { | ||||
| 	size_t plen; | ||||
| 
 | ||||
| 	plen = *src++; | ||||
| 
 | ||||
| 	while (plen > 0) | ||||
| 	{ | ||||
| 		*dst++ = *src++; | ||||
| 		plen--; | ||||
| 	} | ||||
| 	*dst = '\0'; | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| print_sym_name(uint32_t off) | ||||
| { | ||||
| 	char name_str[255] = {0}; | ||||
| 
 | ||||
| 	if (off == 0) | ||||
| 	{ | ||||
| 		return; | ||||
| 	} | ||||
| 	if (off & (1<<31)) | ||||
| 	{ | ||||
| 		strncpy(name_str, strtab_get(off & ~(1<<31)), 255); | ||||
| 		name_str[254] = '\0'; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		pstr2cstr(name_str, psrc.data + off); | ||||
| 	} | ||||
| 
 | ||||
| 	printf("%s", name_str); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| print_sym_section(uint8_t type, uint32_t rel) | ||||
| { | ||||
| 	if (type == FAS_ABS) | ||||
| 	{ | ||||
| 		printf("ABS "); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	if (rel & (1<<31)) | ||||
| 	{ | ||||
| 		printf("UND "); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		printf("%-3" PRIu32 " %-2" PRIu8 " ", rel, type); | ||||
| 	} | ||||
| } | ||||
| /*
 | ||||
| static const char * | ||||
| get_symbol_type(uint8_t type) | ||||
| { | ||||
| 	switch (type) | ||||
| 	{ | ||||
| 	case FAS_ABS: | ||||
| 		return ("ABS"); | ||||
| 	case FAS_REL_32: | ||||
| 		return ("REL_32"); | ||||
| 	default: | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	return ("???"); | ||||
| } | ||||
| */ | ||||
| static void | ||||
| print_symbols(void) | ||||
| { | ||||
| 	size_t symcnt; | ||||
| 	size_t idx; | ||||
| 	struct fas_symbol *sym; | ||||
| 
 | ||||
| 	printf("Symbol table:\n"); | ||||
| 	symcnt = symtab.size / sizeof(struct fas_symbol); | ||||
| 	sym = (struct fas_symbol *)symtab.data; | ||||
| 
 | ||||
| 	printf("   Num: Value              Size Ndx Name\n"); | ||||
| 
 | ||||
| 	for (idx = 0; idx < symcnt; idx++) | ||||
| 	{ | ||||
| 		printf("%6d: ", idx); | ||||
| 		printf("0x%016" PRIx64 " ", sym[idx].value); | ||||
| 		printf("%-4" PRIu8 " ", sym[idx].size); | ||||
| 		//printf("%s ", get_symbol_type(sym[idx].type));
 | ||||
| 		print_sym_section(sym[idx].type, sym[idx].reloc); | ||||
| 		print_sym_name(sym[idx].name_off); | ||||
| 		printf("\n"); | ||||
| /*
 | ||||
| 		printf("\t %04" PRIx16 " : ", sym[idx].flags); | ||||
| 		if (sym[idx].flags & FAS_SYM_DEF) printf("DEF "); | ||||
| 		if (sym[idx].flags & FAS_SYM_ASM_TIME) printf("ASM_TIME "); | ||||
| 		if (sym[idx].flags & FAS_SYM_NOT_FWD_REF) printf("NOT_FWD "); | ||||
| 		if (sym[idx].flags & FAS_SYM_USED) printf("USED "); | ||||
| 		if (sym[idx].flags & FAS_SYM_PRD_USED) printf("PRD_USED "); | ||||
| 		if (sym[idx].flags & FAS_SYM_LPRD_USED) printf("LPRD_USED "); | ||||
| 		if (sym[idx].flags & FAS_SYM_PRD_DEF) printf("PRD_DEF "); | ||||
| 		if (sym[idx].flags & FAS_SYM_LPRD_DEF) printf("LPRD_DEF "); | ||||
| 		if (sym[idx].flags & FAS_SYM_OPT_ADJ) printf("OPT_ADJ "); | ||||
| 		if (sym[idx].flags & FAS_SYM_TWO_CMPLMNT) printf("TWO_CMPLMNT "); | ||||
| 		if (sym[idx].flags & FAS_SYM_MARKER) printf("MARKER "); | ||||
| 		printf("\n"); | ||||
| */ | ||||
| 		/*printf("%X\n", sym[idx].value);*/ | ||||
| 	} | ||||
| 	printf("\n"); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| print_asm_dump(void) | ||||
| { | ||||
| 	struct fas_asmdmp *dmp; | ||||
| 
 | ||||
| 	dmp = (struct fas_asmdmp *)asmdmp.data; | ||||
| 	printf(" 0x%" PRIx32 " 0x%" PRIx64 "\n", dmp->of_off, dmp->addr); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| process_file(char *fname) | ||||
| { | ||||
| 	FILE *fp; | ||||
| 
 | ||||
| 	fp = fopen(fname, "rb"); | ||||
| 	if (fp == NULL) | ||||
| 	{ | ||||
| 		return (EXIT_FAILURE); | ||||
| 	} | ||||
| 
 | ||||
| 	read_header(fp); | ||||
| 	load_table(&strtab, hdr.strtab_off, hdr.strtab_len, fp); | ||||
| 	load_table(&symtab, hdr.symtab_off, hdr.symtab_len, fp); | ||||
| 	load_table(&psrc, hdr.psrc_off, hdr.psrc_len, fp); | ||||
| 	load_table(&asmdmp, hdr.asmdmp_off, hdr.asmdmp_len, fp); | ||||
| 	load_table(§ab, hdr.sectab_off, hdr.sectab_len, fp); | ||||
| 
 | ||||
| 	print_header(); | ||||
| 	print_sections(); | ||||
| 	print_symbols(); | ||||
| 	print_asm_dump(); | ||||
| 
 | ||||
| 	fclose(fp); | ||||
| 
 | ||||
| 	return (EXIT_SUCCESS); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| main(int argc, char *argv[]) | ||||
| { | ||||
| 	while ((argc > 1) && (argv[1][0] == '-')) | ||||
| 	{ | ||||
| 		switch (argv[1][1]) | ||||
| 		{ | ||||
| 		case 'h': | ||||
| 			usage(EXIT_SUCCESS); | ||||
| 			break; | ||||
| 		case 'V': | ||||
| 			version(); | ||||
| 			break; | ||||
| 		default: | ||||
| 			usage(EXIT_FAILURE); | ||||
| 			break; | ||||
| 		} | ||||
| 
 | ||||
| 		argv++; | ||||
| 		argc--; | ||||
| 	} | ||||
| 
 | ||||
| 	if (argc <= 1) usage(EXIT_FAILURE); | ||||
| 
 | ||||
| 	return (process_file(argv[1])); | ||||
| } | ||||
|  | @ -98,7 +98,7 @@ _start: | |||
| 
 | ||||
| 	jmp .skip_fat | ||||
| 
 | ||||
| 	; fallback to fat12	 | ||||
| 	; fallback to fat12 | ||||
| 	; for now fat12 is asumed | ||||
| .fat_fallback: | ||||
| 	mov si, szMsgFatFallback | ||||
|  | @ -129,7 +129,7 @@ _start: | |||
| 	xor bx, bx | ||||
| 
 | ||||
| 	call disk_read_sectors | ||||
| 	 | ||||
| 
 | ||||
| 	; load stage 2 | ||||
| 	mov ax, KERNEL_PRELOAD/0x10 | ||||
| 	mov es, ax | ||||
|  | @ -146,7 +146,7 @@ _start: | |||
| 	call boot_info_print_mmap | ||||
| 
 | ||||
| 	; video information | ||||
| 	;call video_setup | ||||
| 	call video_setup | ||||
| 
 | ||||
| 	; load GDT and enter Protected-Mode | ||||
| 	lgdt [gdt_ptr] | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ struc VesaInfo | |||
| 	.Version               dw ? | ||||
| 	.OEMNamePtr            dd ? | ||||
| 	.Capabilities          dd ? | ||||
| 	.VideoModesPtr         dw ? | ||||
| 	.VideoModesPtr         dd ? | ||||
| 	.CountOf64KBlocks      dw ? | ||||
| 	.OEMSoftwareRevision   dw ? | ||||
| 	.OEMVendorNamePtr      dd ? | ||||
|  | @ -28,7 +28,7 @@ struc VesaModeInfo | |||
| 	.WindowPositioning dd ? | ||||
| 	.BytesPerScanLine  dw ? | ||||
| 
 | ||||
| 	; --   | ||||
| 	; -- | ||||
| 	.Width            dw ? | ||||
| 	.Height           dw ? | ||||
| 	.WidthChar        db ? | ||||
|  | @ -72,11 +72,11 @@ video_setup: | |||
| 	jne .err | ||||
| 	cmp [vesa_block_buffer.Signature], 'VESA' | ||||
| 	jne .err | ||||
| 
 | ||||
| 	push [vesa_block_buffer.OEMProductNamePtr] | ||||
| 	push [vesa_block_buffer.OEMVendorNamePtr] | ||||
| 	push [vesa_block_buffer.CountOf64KBlocks] | ||||
| 	push [vesa_block_buffer.OEMNamePtr] | ||||
| 	; XXX: fix me | ||||
| 	push word [vesa_block_buffer.OEMProductNamePtr] | ||||
| 	push word [vesa_block_buffer.OEMVendorNamePtr] | ||||
| 	push word [vesa_block_buffer.CountOf64KBlocks] | ||||
| 	push word [vesa_block_buffer.OEMNamePtr] | ||||
| 	xor ecx, ecx | ||||
| 	mov cx, [vesa_block_buffer.Version] | ||||
| 	push ecx | ||||
|  | @ -84,7 +84,7 @@ video_setup: | |||
| 	call bios_log | ||||
| 
 | ||||
| 	mov di, vesa_info_block_buffer | ||||
| 	mov bx, [vesa_block_buffer.VideoModesPtr] | ||||
| 	mov ebx, [vesa_block_buffer.VideoModesPtr] | ||||
| 	mov cx, [bx] | ||||
| 	cmp cx, 0xFFFF | ||||
| 	je .err | ||||
|  | @ -110,6 +110,7 @@ vesa_block_buffer VesaInfo | |||
| vesa_info_block_buffer VesaModeInfo | ||||
| 
 | ||||
| szMsgVesaInfo db "Version: %x", CR, LF, "OEM Name: %s", CR, LF, "Total Memory: %d", CR, LF, "Vendor name: %s", CR, LF, "Product name: %s", 0 | ||||
| szMsgVesaModeInfo db "%dx%dx%d", CR, LF, 0 | ||||
| szMsgDetectVideo db "Fetch video information.", 0 | ||||
| szMsgFramebuffer db "Fb: %x", 0 | ||||
| szMsgErrorVesa db "Failed to detect VBE mode", 0 | ||||
|  |  | |||
							
								
								
									
										192
									
								
								include/elf.h
									
										
									
									
									
								
							
							
						
						
									
										192
									
								
								include/elf.h
									
										
									
									
									
								
							|  | @ -1,23 +1,189 @@ | |||
| #ifndef ELF_H | ||||
| # define ELF_H 1 | ||||
| 
 | ||||
| /* spec: https://refspecs.linuxfoundation.org/elf/elf.pdf
 | ||||
|  *       elf(5) | ||||
|  */ | ||||
| # include <stdint.h> | ||||
| 
 | ||||
| # define ELF_MAG0 0x7F | ||||
| # define ELF_MAG1 0x45 | ||||
| # define ELF_MAG2 0x4C | ||||
| # define ELF_MAG3 0x46 | ||||
| # define ELFMAG0 0x7F | ||||
| # define ELFMAG1 0x45 | ||||
| # define ELFMAG2 0x4C | ||||
| # define ELFMAG3 0x46 | ||||
| 
 | ||||
| # define EI_NIDENT 16 | ||||
| # define EI_MAG0    0 | ||||
| # define EI_MAG1    1 | ||||
| # define EI_MAG2    2 | ||||
| # define EI_MAG3    3 | ||||
| # define EI_CLASS   4 | ||||
| # define EI_DATA    5 | ||||
| # define EI_VERSION 6 | ||||
| # define EI_PAD     7 | ||||
| # define EI_NIDENT  16 | ||||
| 
 | ||||
| struct elf_header  | ||||
| { | ||||
| 	uint8_t e_ident[EI_NIDENT]; | ||||
| 	uint16_t e_type; | ||||
| 	uint16_t e_machine; | ||||
| 	uint32_t e_version; | ||||
| }; | ||||
| # define ET_NONE   0 | ||||
| # define ET_REL    1 | ||||
| # define ET_EXEC   2 | ||||
| # define ET_DYN    3 | ||||
| # define ET_CORE   4 | ||||
| # define ET_LOPROC 0xFF00 | ||||
| # define ET_HIPROC 0xFFFF | ||||
| 
 | ||||
| /* TODO */ | ||||
| # define EM_NONE        0 | ||||
| # define EM_M32         1 | ||||
| # define EM_SPARC       2 | ||||
| # define EM_386         3 | ||||
| # define EM_68K         4 | ||||
| # define EM_88K         5 | ||||
| # define EM_860         7 | ||||
| # define EM_MIPS        8 | ||||
| # define EM_MIPS_RS4_BE 10 | ||||
| 
 | ||||
| # define EV_NONE    0 | ||||
| # define EV_CURRENT 1 | ||||
| 
 | ||||
| # define ELFCLASSNONE 0 | ||||
| # define ELFCLASS32   1 | ||||
| # define ELFCLASS64   2 | ||||
| 
 | ||||
| # define ELFDATANONE 0 | ||||
| # define ELFDATA2LSB 1 | ||||
| # define ELFDATA2MSB 2 | ||||
| 
 | ||||
| typedef uint32_t Elf32_Addr; | ||||
| typedef uint16_t Elf32_Half; | ||||
| typedef uint32_t Elf32_Off; | ||||
| typedef int32_t  Elf32_Sword; | ||||
| typedef uint32_t Elf32_Word; | ||||
| 
 | ||||
| typedef struct { | ||||
| 	uint8_t    e_ident[EI_NIDENT]; | ||||
| 	Elf32_Half e_type; | ||||
|     Elf32_Half e_machine; | ||||
|     Elf32_Word e_version; | ||||
| 	Elf32_Addr e_entry; | ||||
|     Elf32_Off  e_phoff; | ||||
| 	Elf32_Off  e_shoff; | ||||
| 	Elf32_Word e_flags; | ||||
| 	Elf32_Half e_ehsize; | ||||
| 	Elf32_Half e_phentsize; | ||||
| 	Elf32_Half e_phnum; | ||||
| 	Elf32_Half e_shentsize; | ||||
| 	Elf32_Half e_shnum; | ||||
|     Elf32_Half e_shstrndx; | ||||
| } Elf32_Ehdr; | ||||
| 
 | ||||
| # define SHN_UNDEF     0 | ||||
| # define SHN_LORESERVE 0xFF00 | ||||
| # define SHN_LOPROC    0xFF00 | ||||
| # define SHN_HIPROC    0xFF1F | ||||
| # define SHN_ABS       0xFFF1 | ||||
| # define SHN_COMMON    0xFFF2 | ||||
| # define SHN_HIRESERVE 0xFFFF | ||||
| 
 | ||||
| # define SHT_NULL     0 | ||||
| # define SHT_PROGBITS 1 | ||||
| # define SHT_SYMTAB   2 | ||||
| # define SHT_STRTAB   3 | ||||
| # define SHT_RELA     4 | ||||
| # define SHT_HASH     5 | ||||
| # define SHT_DYNAMIC  6 | ||||
| # define SHT_NOTE     7 | ||||
| # define SHT_NOBITS   8 | ||||
| # define SHT_REL      9 | ||||
| # define SHT_SHLIB    10 | ||||
| # define SHT_DYNSYM   11 | ||||
| # define SHT_LOPROC   0x70000000 | ||||
| # define SHT_HIPROC   0x7FFFFFFF | ||||
| # define SHT_LOUSER   0x80000000 | ||||
| # define SHT_HIUSER   0xFFFFFFFF | ||||
| 
 | ||||
| # define SHF_WRITE     0x1 | ||||
| # define SHF_ALLOC     0x2 | ||||
| # define SHF_EXECINSTR 0x4 | ||||
| # define SHF_MASKPROC  0xF0000000 | ||||
| 
 | ||||
| typedef struct { | ||||
| 	Elf32_Word sh_name; | ||||
| 	Elf32_Word sh_type; | ||||
| 	Elf32_Word sh_flags; | ||||
| 	Elf32_Addr sh_addr; | ||||
| 	Elf32_Off  sh_offset; | ||||
| 	Elf32_Word sh_size; | ||||
| 	Elf32_Word sh_link; | ||||
| 	Elf32_Word sh_info; | ||||
| 	Elf32_Word sh_addralign; | ||||
| 	Elf32_Word sh_entsize; | ||||
| } Elf32_Shdr; | ||||
| 
 | ||||
| # define STN_UNDER 0 | ||||
| 
 | ||||
| typedef struct { | ||||
|     Elf32_Word st_name; | ||||
| 	Elf32_Addr st_value; | ||||
| 	Elf32_Word st_size; | ||||
| 	uint8_t    st_info; | ||||
| 	uint8_t    st_other; | ||||
| 	Elf32_Half st_shndx; | ||||
| } Elf32_Sym; | ||||
| 
 | ||||
| # define ELF32_ST_BIND(x)    ((x)>>4) | ||||
| # define ELF32_ST_TYPE(x)    ((x)&0xf) | ||||
| # define ELF32_ST_INFO(b, t) (((b)<<4)+((t)&0xf)) | ||||
| 
 | ||||
| # define STB_LOCAL   0 | ||||
| # define STB_GLOBAL  1 | ||||
| # define STB_WEAK    2 | ||||
| # define STB_LOPROC  13 | ||||
| # define STB_HIPROC  15 | ||||
| 
 | ||||
| # define STT_NOTYPE  0 | ||||
| # define STT_OBJECT  1 | ||||
| # define STT_FUNC    2 | ||||
| # define STT_SECTION 3 | ||||
| # define STT_FILE    4 | ||||
| # define STT_LOPROC  13 | ||||
| # define STT_HIPROC  15 | ||||
| 
 | ||||
| typedef struct { | ||||
| 	Elf32_Addr r_offset; | ||||
| 	Elf32_Word r_info; | ||||
| } Elf32_Rel; | ||||
| 
 | ||||
| typedef struct { | ||||
| 	Elf32_Addr  r_offset; | ||||
| 	Elf32_Word  r_info; | ||||
| 	Elf32_Sword r_addend; | ||||
| } Elf32_Rela; | ||||
| 
 | ||||
| # define ELF32_R_SYM(x)    ((x)>>8) | ||||
| # define ELF32_R_TYPE(x)   ((uint8_t)(i)); | ||||
| # define ELF32_R_INFO(s,t) (((s)<<8)+(uint8_t)(t)) | ||||
| 
 | ||||
| typedef struct { | ||||
| 	Elf32_Word p_type; | ||||
| 	Elf32_Off  p_offset; | ||||
| 	Elf32_Addr p_vaddr; | ||||
| 	Elf32_Addr p_paddr; | ||||
| 	Elf32_Word p_filesz; | ||||
| 	Elf32_Word p_memsz; | ||||
| 	Elf32_Word p_flags; | ||||
| 	Elf32_Word p_align; | ||||
| } Elf32_Phdr; | ||||
| 
 | ||||
| # define PT_NULL    0 | ||||
| # define PT_LOAD    1 | ||||
| # define PT_DYNAMIC 2 | ||||
| # define PT_INTERP  3 | ||||
| # define PT_NOTE    4 | ||||
| # define PT_SHLIB   5 | ||||
| # define PT_PHDR    6 | ||||
| # define PT_LOPROC  0x70000000 | ||||
| # define PT_HIPROC  0x7FFFFFFF | ||||
| 
 | ||||
| # define PF_X        0x1 | ||||
| # define PF_W        0x2 | ||||
| # define PF_R        0x4 | ||||
| # define PF_MASKPROC 0xF0000000 | ||||
| 
 | ||||
| #endif /* !ELF_H */ | ||||
|  |  | |||
							
								
								
									
										140
									
								
								include/fas.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								include/fas.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,140 @@ | |||
| #ifndef FAS_H | ||||
| # define FAS_H 1 | ||||
| 
 | ||||
| # include <stdint.h> | ||||
| 
 | ||||
| # define FAS_MAGIC 0x1A736166 | ||||
| 
 | ||||
| typedef struct fas_header | ||||
| { | ||||
| 	uint32_t magic; | ||||
| 	uint8_t  ver_major; | ||||
| 	uint8_t  ver_minor; | ||||
| 	uint16_t length; | ||||
| 	uint32_t ifnm_off; | ||||
| 	uint32_t ofnm_off; | ||||
| 	uint32_t strtab_off; | ||||
| 	uint32_t strtab_len; | ||||
| 	uint32_t symtab_off; | ||||
| 	uint32_t symtab_len; | ||||
| 	uint32_t psrc_off; | ||||
| 	uint32_t psrc_len; | ||||
| 	uint32_t asmdmp_off; | ||||
| 	uint32_t asmdmp_len; | ||||
| 	uint32_t sectab_off; | ||||
| 	uint32_t sectab_len; | ||||
| 	uint32_t symref_off; | ||||
| 	uint32_t symref_len; | ||||
| } FAS_Hdr; | ||||
| 
 | ||||
| # define FAS_SYM_DEF         0x001 | ||||
| # define FAS_SYM_ASM_TIME    0x002 | ||||
| # define FAS_SYM_NOT_FWD_REF 0x004 | ||||
| # define FAS_SYM_USED        0x008 | ||||
| # define FAS_SYM_PRD_USED    0x010 | ||||
| # define FAS_SYM_LPRD_USED   0x020 | ||||
| # define FAS_SYM_PRD_DEF     0x040 | ||||
| # define FAS_SYM_LPRD_DEF    0x080 | ||||
| # define FAS_SYM_OPT_ADJ     0x100 | ||||
| # define FAS_SYM_TWO_CMPLMNT 0x200 | ||||
| # define FAS_SYM_MARKER      0x400 | ||||
| 
 | ||||
| enum fas_symbol_type | ||||
| { | ||||
| 	FAS_ABS, | ||||
| 	FAS_REL_SEG, | ||||
| 	FAS_REL_32, | ||||
| 	FAS_REL_R_32, | ||||
| 	FAS_REL_64, | ||||
| 	FAS_GOT_32, | ||||
| 	FAS_PLT_32, | ||||
| 	FAS_PLT_R_32 | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| typedef struct fas_symbol | ||||
| { | ||||
| 	uint64_t value; | ||||
| 	uint16_t flags; | ||||
| 	uint8_t  size; | ||||
| 	uint8_t  type; | ||||
| 	uint32_t ext_SIB; | ||||
| 	uint16_t pass_ldef; | ||||
| 	uint16_t pass_lused; | ||||
| 	uint32_t reloc; | ||||
| 	uint32_t name_off; | ||||
| 	uint32_t psrc_line_off; | ||||
| } FAS_Sym; | ||||
| 
 | ||||
| struct fas_psrc_line | ||||
| { | ||||
| 	uint32_t from; | ||||
| 	uint32_t lineno; | ||||
| 	uint32_t src_off; | ||||
| 	uint32_t macro_off; | ||||
| 	uint8_t  tokens[]; | ||||
| }; | ||||
| 
 | ||||
| enum fas_code | ||||
| { | ||||
| 	FAS_CODE_16 = 16, | ||||
| 	FAS_CODE_32 = 32, | ||||
| 	FAS_CODE_64 = 64 | ||||
| }; | ||||
| 
 | ||||
| struct fas_asmdmp | ||||
| { | ||||
| 	uint32_t of_off; | ||||
| 	uint32_t psrc_line_off; | ||||
| 	uint64_t addr; | ||||
| 	uint32_t ext_SIB; | ||||
| 	uint32_t reloc; | ||||
| 	uint8_t  type; | ||||
| 	uint8_t  code; | ||||
| 	uint8_t  virt; | ||||
| 	uint8_t  high; | ||||
| }; | ||||
| 
 | ||||
| enum fas_register | ||||
| { | ||||
| 	FAS_REG_BX   = 0x23, | ||||
| 	FAS_REG_BP   = 0x25, | ||||
| 	FAS_REG_SI   = 0x26, | ||||
| 	FAS_REG_DI   = 0x27, | ||||
| 	FAS_REG_EAX  = 0x40, | ||||
| 	FAS_REG_ECX  = 0x41, | ||||
| 	FAS_REG_EDX  = 0x42, | ||||
| 	FAS_REG_EBX  = 0x43, | ||||
| 	FAS_REG_ESP  = 0x44, | ||||
| 	FAS_REG_EBP  = 0x45, | ||||
| 	FAS_REG_ESI  = 0x46, | ||||
| 	FAS_REG_EDI  = 0x47, | ||||
| 	FAS_REG_R8D  = 0x48, | ||||
| 	FAS_REG_R9D  = 0x49, | ||||
| 	FAS_REG_R10D = 0x4A, | ||||
| 	FAS_REG_R11D = 0x4B, | ||||
| 	FAS_REG_R12D = 0x4C, | ||||
| 	FAS_REG_R13D = 0x4D, | ||||
| 	FAS_REG_R14D = 0x4E, | ||||
| 	FAS_REG_R15D = 0x4F, | ||||
| 	FAS_REG_RAX  = 0x80, | ||||
| 	FAS_REG_RCX  = 0x81, | ||||
| 	FAS_REG_RDX  = 0x82, | ||||
| 	FAS_REG_RBX  = 0x83, | ||||
| 	FAS_REG_RSP  = 0x84, | ||||
| 	FAS_REG_RBP  = 0x85, | ||||
| 	FAS_REG_RSI  = 0x86, | ||||
| 	FAS_REG_RDI  = 0x87, | ||||
| 	FAS_REG_R8   = 0x88, | ||||
| 	FAS_REG_R9   = 0x89, | ||||
| 	FAS_REG_R10  = 0x8A, | ||||
| 	FAS_REG_R11  = 0x8B, | ||||
| 	FAS_REG_R12  = 0x8C, | ||||
| 	FAS_REG_R13  = 0x8D, | ||||
| 	FAS_REG_R14  = 0x8E, | ||||
| 	FAS_REG_R15  = 0x8F, | ||||
| 	FAS_REG_EIP  = 0x94, | ||||
| 	FAS_REG_RIP  = 0x98, | ||||
| }; | ||||
| 
 | ||||
| #endif /* !FAS_H */ | ||||
|  | @ -1,4 +1,9 @@ | |||
| TARGET	= ld$(EXEXT) parted$(EXEXT) readcoff$(EXEXT) elf2coff$(EXEXT) ar$(EXEXT) ranlib$(EXEXT) | ||||
| TARGET	= ld$(EXEXT) parted$(EXEXT) readcoff$(EXEXT) \
 | ||||
| 			elf2coff$(EXEXT) ar$(EXEXT) ranlib$(EXEXT) \
 | ||||
| 			fasdump$(EXEXT) fas2sym$(EXEXT) | ||||
| 
 | ||||
| FAS2SYM_SRCS = main.c fas.c elf.c buffer.c | ||||
| FAS2SYM_OBJS = $(addprefix ../bin/fas2sym/, $(FAS2SYM_SRCS:.c=.o)) | ||||
| 
 | ||||
| .PHONY: all | ||||
| all: $(TARGET) | ||||
|  | @ -21,6 +26,12 @@ ranlib$(EXEXT): ../bin/ranlib/main.c ../bin/ar/archive.c | |||
| ar$(EXEXT): ../bin/ar/main.c | ||||
| 	$(TOOL_CC) -o $@ $^ $(CFLAGS) $(LDFLAGS) | ||||
| 
 | ||||
| fasdump$(EXEXT): ../bin/fasdump/main.c | ||||
| 	$(TOOL_CC) -o $@ $^ $(CFLAGS) $(LDFLAGS) | ||||
| 
 | ||||
| fas2sym$(EXEXT): $(FAS2SYM_OBJS) | ||||
| 	$(TOOL_CC) -o $@ $^ $(CFLAGS) $(LDFLAGS) | ||||
| 
 | ||||
| .PHONY: install | ||||
| install: $(TARGET) | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue