Further refactor code

This commit is contained in:
d0p1 🏳️‍⚧️ 2025-02-11 13:07:04 +01:00
parent db4e043cd9
commit ca1e24c395
28 changed files with 661 additions and 368 deletions

View file

@ -25,5 +25,18 @@ AC_CHECK_INCLUDES_DEFAULT
AC_C_CONST
AC_C_INLINE
AC_C_BIGENDIAN
AC_C_CHAR_UNSIGNED
AC_CHECK_HEADERS([
libgen.h
sys/queue.h
])
AC_ARG_ENABLE([memory_debug],
[AS_HELP_STRING([--enable-memory-debug=<level>], [enable memory debuging with <level> (1, 2, 3)])])
AS_CASE([$enable_memory_debug],
[[[1-3]]], [AC_DEFINE_UNQUOTED([TCC_MEMORY_DEBUG], [$enable_memory_debug], [enable memory debug])],
[*yes*], [AC_DEFINE([TCC_MEMORY_DEBUG], [1], [enable memory debug])])
AC_OUTPUT

View file

@ -1,5 +1,5 @@
noinst_LIBRARIES = libtcc.a
libtcc_a_SOURCES = libtcc.c option.c tccpp.c tccgen.c \
libtcc_a_SOURCES = libtcc.c option.c path.c memory.c tccpp.c tccgen.c \
tccasm.c tccelf.c \
i386/gen.c i386/link.c \
i386/asm.c tcccoff.c

View file

@ -1,11 +1,13 @@
#ifndef LIBTCC_H
# define LIBTCC_H 1
# include <stddef.h>
# ifdef __cplusplus
extern "C" {
# endif /* __cplusplus */
typedef void *TCCReallocFunc(void *ptr, unsigned long size);
typedef void *TCCReallocFunc(void *ptr, size_t size);
/**
* @brief set custom allocator for all allocations (optional), NULL for default.
*/

View file

@ -83,18 +83,6 @@ extern long double strtold (const char *__nptr, char **__endptr);
#define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
#endif
#ifdef _WIN32
# define IS_DIRSEP(c) (c == '/' || c == '\\')
# define IS_ABSPATH(p) (IS_DIRSEP(p[0]) || (p[0] && p[1] == ':' && IS_DIRSEP(p[2])))
# define PATHCMP stricmp
# define PATHSEP ";"
#else
# define IS_DIRSEP(c) (c == '/')
# define IS_ABSPATH(p) IS_DIRSEP(p[0])
# define PATHCMP strcmp
# define PATHSEP ":"
#endif
/* -------------------------------------------- */
/* parser debug */
@ -180,6 +168,7 @@ extern long double strtold (const char *__nptr, char **__endptr);
#include <libtcc.h>
#include <tcc/elf.h>
#include <tcc/coff.h>
#include <tcc/utils/cstring.h>
/* -------------------------------------------- */
@ -200,7 +189,7 @@ extern long double strtold (const char *__nptr, char **__endptr);
# define REL_SECTION_FMT ".rel%s"
/* target address type */
#define addr_t ElfW(Addr)
typedef uint32_t addr_t;
#define ElfSym ElfW(Sym)
#define LONG_SIZE 4
@ -232,12 +221,6 @@ typedef struct TokenSym {
typedef int nwchar_t;
typedef struct CString {
int size; /* size in bytes */
int size_allocated;
char *data; /* nwchar_t* in cases */
} CString;
/* type definition */
typedef struct CType {
int t;
@ -341,6 +324,14 @@ typedef struct Section {
unsigned char *data; /* section data */
unsigned long data_allocated; /* used for realloc() handling */
TCCState *s1;
/**/
char *c_name[8];
addr_t c_addr;
int32_t c_flags;
/**/
int sh_name; /* elf section name (only used during output) */
int sh_num; /* elf section number */
int sh_type; /* elf section type */
@ -549,10 +540,7 @@ struct TCCState {
char *tcc_lib_path; /* CONFIG_TCCDIR or -B option */
char *rpath; /* as specified on the command line (-Wl,-rpath=) */
char *elf_entryname; /* "_start" unless set */
char *init_symbol; /* symbols to call at load-time (not used currently) */
char *fini_symbol; /* symbols to call at unload-time (not used currently) */
char *mapfile; /* create a mapfile (not used currently) */
char *entryname; /* "_start" unless set */
/* output type, see TCC_OUTPUT_XXX */
int output_type;
@ -771,30 +759,6 @@ extern struct TCCState *tcc_state;
extern void** stk_data;
extern int nb_stk_data;
/* public functions currently used by the tcc main function */
PUB_FUNC char *tcc_basename(const char *name);
PUB_FUNC char *tcc_fileextension (const char *name);
/* all allocations - even MEM_DEBUG - use these */
PUB_FUNC void tcc_free(void *ptr);
PUB_FUNC void *tcc_malloc(unsigned long size);
PUB_FUNC void *tcc_mallocz(unsigned long size);
PUB_FUNC void *tcc_realloc(void *ptr, unsigned long size);
PUB_FUNC char *tcc_strdup(const char *str);
#ifdef MEM_DEBUG
#define tcc_free(ptr) tcc_free_debug(ptr)
#define tcc_malloc(size) tcc_malloc_debug(size, __FILE__, __LINE__)
#define tcc_mallocz(size) tcc_mallocz_debug(size, __FILE__, __LINE__)
#define tcc_realloc(ptr,size) tcc_realloc_debug(ptr, size, __FILE__, __LINE__)
#define tcc_strdup(str) tcc_strdup_debug(str, __FILE__, __LINE__)
PUB_FUNC void tcc_free_debug(void *ptr);
PUB_FUNC void *tcc_malloc_debug(unsigned long size, const char *file, int line);
PUB_FUNC void *tcc_mallocz_debug(unsigned long size, const char *file, int line);
PUB_FUNC void *tcc_realloc_debug(void *ptr, unsigned long size, const char *file, int line);
PUB_FUNC char *tcc_strdup_debug(const char *str, const char *file, int line);
#endif
PUB_FUNC int _tcc_error_noabort(const char *fmt, ...) __attribute__ ((format (printf, (1), (2))));
PUB_FUNC __attribute__((noreturn)) void _tcc_error(const char *fmt, ...) __attribute__ ((format (printf, (1), (2))));
PUB_FUNC void _tcc_warning(const char *fmt, ...) __attribute__ ((format (printf, (1), (2))));
@ -804,14 +768,6 @@ PUB_FUNC void _tcc_warning(const char *fmt, ...) __attribute__ ((format (printf,
/* other utilities */
void dynarray_add(void *ptab, int *nb_ptr, void *data);
void dynarray_reset(void *pp, int *n);
void cstr_ccat(CString *cstr, int ch);
void cstr_cat(CString *cstr, const char *str, int len);
void cstr_wccat(CString *cstr, int ch);
void cstr_new(CString *cstr);
void cstr_free(CString *cstr);
int cstr_printf(CString *cs, const char *fmt, ...) __attribute__ ((format (printf, (2), (3))));
int cstr_vprintf(CString *cstr, const char *fmt, va_list ap);
void cstr_reset(CString *cstr);
void tcc_open_bf(TCCState *s1, const char *filename, int initlen);
int tcc_open(TCCState *s1, const char *filename);
void tcc_close(void);
@ -1071,7 +1027,6 @@ void relocate_sections(TCCState *s1);
ssize_t full_read(int fd, void *buf, size_t count);
void *load_data(int fd, unsigned long file_offset, unsigned long size);
int tcc_object_type(int fd, ElfW(Ehdr) *h);
int tcc_load_object_file(TCCState *s1, int fd, unsigned long file_offset);
int tcc_load_archive(TCCState *s1, int fd, int alacarte);
void add_array(TCCState *s1, const char *sec, int c);

29
libtcc/include/tcc/io.h Normal file
View file

@ -0,0 +1,29 @@
#ifndef TCC_IO_H
# define TCC_IO_H 1
# include <stdint.h>
# define IO_BUF_SIZE 8192
typedef struct BufferedFile {
uint8_t *buf_ptr;
uint8_t *buf_end;
int fd;
struct BufferedFile *prev;
int line_num; /** current line number - here to simplify code */
int line_ref; /** tcc -E: last printed line */
int ifndef_macro; /** #ifndef macro / #endif search */
int ifndef_macro_saved; /** saved ifndef_macro */
int *ifdef_stack_ptr; /** ifdef_stack value at the start of the file */
int include_next_index; /** next search path */
int prev_tok_flags; /** saved tok_flags */
char *filename[1024]; /** filename */
char *true_filename; /** filename not modified by # line directive */
unsigned char unget[4];
unsigned char buffer[1]; /** extra size for CH_EOB char */
} BufferedFile;
# define CH_EOB '\\' /** end of buffer or '\0' char in file */
# define CH_EOF (-1) /** end of file */
#endif /* !TCC_IO_H */

View file

@ -0,0 +1,27 @@
#ifndef TCC_MEMORY_H
# define TCC_MEMORY_H 1
# include <stddef.h>
void tcc_free(void *ptr);
void *tcc_malloc(size_t size);
void *tcc_mallocz(size_t size);
void *tcc_realloc(void *ptr, size_t size);
char *tcc_strdup(const char *str);
# ifdef TCC_MEMORY_DEBUG
# define tcc_free(ptr) tcc_free_debug(ptr);
# define tcc_malloc(size) tcc_malloc_debug(size, __FILE__, __LINE__)
# define tcc_mallocz(size) tcc_mallocz_debug(size, __FILE__, __LINE__)
# define tcc_realloc(ptr, size) tcc_realloc_debug(ptr, size, __FILE__, __LINE__)
# define tcc_strdup(str) tcc_strdup_debug(str, __FILE__, __LINE__)
void tcc_free_debug(void *ptr);
void *tcc_malloc_debug(size_t size, const char *file, int line);
void *tcc_mallocz_debug(size_t size, const char *file, int line);
void *tcc_realloc_debug(void *ptr, size_t size, const char *file, int line);
void *tcc_strdup_debug(const char *str, const char *file, int line);
void tcc_memcheck(int d);
# endif /* TCC_MEMORY_DEBUG */
#endif /* !TCC_MEMORY_H */

View file

@ -0,0 +1,10 @@
#ifndef TCC_OBJECT_H
# define TCC_OBJECT_H 1
# define TCC_BINTYPE_NONE 0
# define TCC_BINTYPE_COFF 1
# define TCC_BINTYPE_ARCHIVE 2
int tcc_object_type(int fd, void *h);
#endif /* !TCC_OBJECT_H */

View file

@ -1,5 +1,5 @@
#ifndef LIBTCC_OBJECT_ARCHIVE_H
# define LIBTCC_OBJECT_ARCHIVE_H 1
#ifndef TCC_OBJECT_ARCHIVE_H
# define TCC_OBJECT_ARCHIVE_H 1
/**
* @defgroup object_archive UNIX Archive
@ -32,4 +32,4 @@ typedef struct Archive {
* @}
*/
#endif /* !LIBTCC_OBJECT_AR_H */
#endif /* !TCC_OBJECT_AR_H */

View file

@ -0,0 +1,4 @@
#ifndef TCC_OBJECT_BINARY_H
# define TCC_OBJECT_BINARY_H 1
#endif /* TCC_OBJECT_BINARY_H */

View file

@ -1,5 +1,5 @@
#ifndef LIBTCC_OBJECT_COFF_H
# define LIBTCC_OBJECT_COFF_H 1
#ifndef TCC_OBJECT_COFF_H
# define TCC_OBJECT_COFF_H 1
# include <stdint.h>
@ -66,4 +66,4 @@ typedef struct COFFSectionHeader {
* @}
*/
#endif /* !LIBTCC_COFF_H */
#endif /* !TCC_COFF_H */

View file

@ -1,5 +1,5 @@
#ifndef LIBTCC_OPTION_H
# define LIBTCC_OPTION_H 1
#ifndef TCC_OPTION_H
# define TCC_OPTION_H 1
# include <stdint.h>
@ -23,4 +23,4 @@ typedef struct TCCState TCCState;
int tcc_parse_args(TCCState *s, int *argc, char ***argv, int optind);
void tcc_add_options(TCCOption *opts);
#endif /* LIBTCC_OPTION_H */
#endif /* TCC_OPTION_H */

19
libtcc/include/tcc/path.h Normal file
View file

@ -0,0 +1,19 @@
#ifndef TCC_PATH_H
# define TCC_PATH_H 1
#ifdef _WIN32
# define IS_DIRSEP(c) (c == '/' || c == '\\')
# define IS_ABSPATH(p) (IS_DIRSEP(p[0]) || (p[0] && p[1] == ':' && IS_DIRSEP(p[2])))
# define PATHCMP stricmp
# define PATHSEP ";"
#else
# define IS_DIRSEP(c) (c == '/')
# define IS_ABSPATH(p) IS_DIRSEP(p[0])
# define PATHCMP strcmp
# define PATHSEP ":"
#endif
char *tcc_basename(const char *name);
char *tcc_fileextension (const char *name);
#endif /* !TCC_PATH_H */

View file

@ -1,10 +1,10 @@
#ifndef LIBTCC_UTILS_CSTR_H
# define LIBTCC_UTILS_CSTR_H 1
#ifndef TCC_UTILS_CSTRING_H
# define TCC_UTILS_CSTRING_H 1
# include <stdarg.h>
typedef struct CString {
int size;
int size; /** size in bytes */
int size_allocated;
char *data;
} CString;
@ -14,8 +14,8 @@ void cstr_cat(CString *cstr, const char *str, int len);
void cstr_wccat(CString *cstr, int ch);
void cstr_new(CString *cstr);
void cstr_free(CString *cstr);
int cstr_printf(CString *cs, const char *fmt, ...) __attribute__ ((format (printf, (2), (3))));
int cstr_printf(CString *cs, const char *fmt, ...) __attribute__((format(printf, (2), (3))));
int cstr_vprintf(CString *cstr, const char *fmt, va_list ap);
void cstr_reset(CString *cstr);
#endif /* !LIBTCC_UTILS_CSTR_H */
#endif /* !TCC_UTILS_CSTRING_H */

View file

@ -18,7 +18,14 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif /* HAVE_CONFIG_H */
#include <tcc.h>
#include <tcc/path.h>
#include <tcc/memory.h>
#include <tcc/object.h>
#include "utils/string.h"
/********************************************************/
@ -79,26 +86,6 @@ PUB_FUNC void tcc_exit_state(TCCState *s1)
POST_SEM(&tcc_compile_sem);
}
/* extract the basename of a file */
PUB_FUNC char *tcc_basename(const char *name)
{
char *p = strchr(name, 0);
while (p > name && !IS_DIRSEP(p[-1]))
--p;
return p;
}
/* extract extension part of a file
*
* (if no extension, return pointer to end-of-string)
*/
PUB_FUNC char *tcc_fileextension (const char *name)
{
char *b = tcc_basename(name);
char *e = strrchr(b, '.');
return e ? e : strchr(b, 0);
}
char *tcc_load_text(int fd)
{
int len = lseek(fd, 0, SEEK_END);
@ -111,247 +98,6 @@ char *tcc_load_text(int fd)
/********************************************************/
/* memory management */
static void *default_reallocator(void *ptr, unsigned long size)
{
void *ptr1;
if (size == 0) {
free(ptr);
ptr1 = NULL;
}
else {
ptr1 = realloc(ptr, size);
if (!ptr1) {
fprintf(stderr, "memory full\n");
exit (1);
}
}
return ptr1;
}
/* global so that every tcc_alloc()/tcc_free() call doesn't need to be changed */
static void *(*reallocator)(void*, unsigned long) = default_reallocator;
void tcc_set_realloc(TCCReallocFunc *realloc)
{
reallocator = realloc ? realloc : default_reallocator;
}
/* in case MEM_DEBUG is #defined */
#undef tcc_free
#undef tcc_malloc
#undef tcc_realloc
#undef tcc_mallocz
#undef tcc_strdup
PUB_FUNC void tcc_free(void *ptr)
{
reallocator(ptr, 0);
}
PUB_FUNC void *tcc_malloc(unsigned long size)
{
return reallocator(0, size);
}
PUB_FUNC void *tcc_realloc(void *ptr, unsigned long size)
{
return reallocator(ptr, size);
}
PUB_FUNC void *tcc_mallocz(unsigned long size)
{
void *ptr;
ptr = tcc_malloc(size);
if (size)
memset(ptr, 0, size);
return ptr;
}
PUB_FUNC char *tcc_strdup(const char *str)
{
char *ptr;
ptr = tcc_malloc(strlen(str) + 1);
strcpy(ptr, str);
return ptr;
}
#ifdef MEM_DEBUG
#define MEM_DEBUG_MAGIC1 0xFEEDDEB1
#define MEM_DEBUG_MAGIC2 0xFEEDDEB2
#define MEM_DEBUG_MAGIC3 0xFEEDDEB3
#define MEM_DEBUG_FILE_LEN 40
#define MEM_DEBUG_CHECK3(header) \
((mem_debug_header_t*)((char*)header + header->size))->magic3
#define MEM_USER_PTR(header) \
((char *)header + offsetof(mem_debug_header_t, magic3))
#define MEM_HEADER_PTR(ptr) \
(mem_debug_header_t *)((char*)ptr - offsetof(mem_debug_header_t, magic3))
struct mem_debug_header {
unsigned magic1;
unsigned size;
struct mem_debug_header *prev;
struct mem_debug_header *next;
int line_num;
char file_name[MEM_DEBUG_FILE_LEN + 1];
unsigned magic2;
__attribute__((aligned(16))) unsigned char magic3[4];
};
typedef struct mem_debug_header mem_debug_header_t;
TCC_SEM(static mem_sem);
static mem_debug_header_t *mem_debug_chain;
static unsigned mem_cur_size;
static unsigned mem_max_size;
static int nb_states;
static mem_debug_header_t *malloc_check(void *ptr, const char *msg)
{
mem_debug_header_t * header = MEM_HEADER_PTR(ptr);
if (header->magic1 != MEM_DEBUG_MAGIC1 ||
header->magic2 != MEM_DEBUG_MAGIC2 ||
read32le(MEM_DEBUG_CHECK3(header)) != MEM_DEBUG_MAGIC3 ||
header->size == (unsigned)-1) {
fprintf(stderr, "%s check failed\n", msg);
if (header->magic1 == MEM_DEBUG_MAGIC1)
fprintf(stderr, "%s:%u: block allocated here.\n",
header->file_name, header->line_num);
exit(1);
}
return header;
}
PUB_FUNC void *tcc_malloc_debug(unsigned long size, const char *file, int line)
{
int ofs;
mem_debug_header_t *header;
if (!size)
return NULL;
header = tcc_malloc(sizeof(mem_debug_header_t) + size);
header->magic1 = MEM_DEBUG_MAGIC1;
header->magic2 = MEM_DEBUG_MAGIC2;
header->size = size;
write32le(MEM_DEBUG_CHECK3(header), MEM_DEBUG_MAGIC3);
header->line_num = line;
ofs = strlen(file) - MEM_DEBUG_FILE_LEN;
strncpy(header->file_name, file + (ofs > 0 ? ofs : 0), MEM_DEBUG_FILE_LEN);
header->file_name[MEM_DEBUG_FILE_LEN] = 0;
WAIT_SEM(&mem_sem);
header->next = mem_debug_chain;
header->prev = NULL;
if (header->next)
header->next->prev = header;
mem_debug_chain = header;
mem_cur_size += size;
if (mem_cur_size > mem_max_size)
mem_max_size = mem_cur_size;
POST_SEM(&mem_sem);
return MEM_USER_PTR(header);
}
PUB_FUNC void tcc_free_debug(void *ptr)
{
mem_debug_header_t *header;
if (!ptr)
return;
header = malloc_check(ptr, "tcc_free");
WAIT_SEM(&mem_sem);
mem_cur_size -= header->size;
header->size = (unsigned)-1;
if (header->next)
header->next->prev = header->prev;
if (header->prev)
header->prev->next = header->next;
if (header == mem_debug_chain)
mem_debug_chain = header->next;
POST_SEM(&mem_sem);
tcc_free(header);
}
PUB_FUNC void *tcc_mallocz_debug(unsigned long size, const char *file, int line)
{
void *ptr;
ptr = tcc_malloc_debug(size,file,line);
if (size)
memset(ptr, 0, size);
return ptr;
}
PUB_FUNC void *tcc_realloc_debug(void *ptr, unsigned long size, const char *file, int line)
{
mem_debug_header_t *header;
int mem_debug_chain_update = 0;
if (!ptr)
return tcc_malloc_debug(size, file, line);
if (!size) {
tcc_free_debug(ptr);
return NULL;
}
header = malloc_check(ptr, "tcc_realloc");
WAIT_SEM(&mem_sem);
mem_cur_size -= header->size;
mem_debug_chain_update = (header == mem_debug_chain);
header = tcc_realloc(header, sizeof(mem_debug_header_t) + size);
header->size = size;
write32le(MEM_DEBUG_CHECK3(header), MEM_DEBUG_MAGIC3);
if (header->next)
header->next->prev = header;
if (header->prev)
header->prev->next = header;
if (mem_debug_chain_update)
mem_debug_chain = header;
mem_cur_size += size;
if (mem_cur_size > mem_max_size)
mem_max_size = mem_cur_size;
POST_SEM(&mem_sem);
return MEM_USER_PTR(header);
}
PUB_FUNC char *tcc_strdup_debug(const char *str, const char *file, int line)
{
char *ptr;
ptr = tcc_malloc_debug(strlen(str) + 1, file, line);
strcpy(ptr, str);
return ptr;
}
PUB_FUNC void tcc_memcheck(int d)
{
WAIT_SEM(&mem_sem);
nb_states += d;
if (0 == nb_states && mem_cur_size) {
mem_debug_header_t *header = mem_debug_chain;
fflush(stdout);
fprintf(stderr, "MEM_DEBUG: mem_leak= %d bytes, mem_max_size= %d bytes\n",
mem_cur_size, mem_max_size);
while (header) {
fprintf(stderr, "%s:%u: error: %u bytes leaked\n",
header->file_name, header->line_num, header->size);
header = header->next;
}
fflush(stderr);
mem_cur_size = 0;
mem_max_size = 0;
mem_debug_chain = NULL;
#if MEM_DEBUG-0 == 2
exit(2);
#endif
}
POST_SEM(&mem_sem);
}
/* restore the debug versions */
#define tcc_free(ptr) tcc_free_debug(ptr)
#define tcc_malloc(size) tcc_malloc_debug(size, __FILE__, __LINE__)
#define tcc_mallocz(size) tcc_mallocz_debug(size, __FILE__, __LINE__)
#define tcc_realloc(ptr,size) tcc_realloc_debug(ptr, size, __FILE__, __LINE__)
#define tcc_strdup(str) tcc_strdup_debug(str, __FILE__, __LINE__)
#endif /* MEM_DEBUG */
#ifdef _WIN32
# define realpath(file, buf) _fullpath(buf, file, 260)
#endif
@ -699,7 +445,7 @@ TCCState *tcc_new(void)
TCCState *s;
s = tcc_mallocz(sizeof(TCCState));
#ifdef MEM_DEBUG
#ifdef TCC_MEMORY_DEBUG
tcc_memcheck(1);
#endif
@ -714,7 +460,7 @@ TCCState *tcc_new(void)
s->ms_extensions = 1;
s->unwind_tables = 1;
#ifdef CHAR_IS_UNSIGNED
#ifdef __CHAR_UNSIGNED__
s->char_is_unsigned = 1;
#endif
s->seg_size = 32;
@ -745,10 +491,7 @@ void tcc_delete(TCCState *s1)
tcc_free(s1->tcc_lib_path);;
tcc_free(s1->rpath);
tcc_free(s1->elf_entryname);
tcc_free(s1->init_symbol);
tcc_free(s1->fini_symbol);
tcc_free(s1->mapfile);
tcc_free(s1->entryname);
tcc_free(s1->outfile);
tcc_free(s1->deps_outfile);
dynarray_reset(&s1->files, &s1->nb_files);
@ -759,7 +502,7 @@ void tcc_delete(TCCState *s1)
cstr_free(&s1->cmdline_incl);
cstr_free(&s1->linker_arg);
tcc_free(s1);
#ifdef MEM_DEBUG
#ifdef TCC_MEMORY_DEBUG
tcc_memcheck(-1);
#endif
}
@ -989,6 +732,10 @@ void tcc_set_lib_path(TCCState *s, const char *path)
/********************************************************/
/* options parser */
#ifdef TCC_MEMORY_DEBUG
extern size_t mem_max_size;
#endif /* TCC_MEMORY_DEBUG */
PUB_FUNC void tcc_print_stats(TCCState *s1, unsigned total_time)
{
if (!total_time)
@ -1005,7 +752,7 @@ PUB_FUNC void tcc_print_stats(TCCState *s1, unsigned total_time)
s1->total_output[2],
s1->total_output[3]
);
#ifdef MEM_DEBUG
#ifdef TCC_MEMORY_DEBUG
fprintf(stderr, "# memory usage");
fprintf(stderr, " %d max (bytes)\n", mem_max_size);
#endif

339
libtcc/memory.c Normal file
View file

@ -0,0 +1,339 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif /* HAVE_CONFIG_H */
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <tcc.h>
#ifdef TCC_MEMORY_DEBUG
# undef tcc_free
# undef tcc_malloc
# undef tcc_mallocz
# undef tcc_realloc
# undef tcc_strdup
#endif /* TCC_MEMORY_DEBUG */
static void *
default_reallocator(void *ptr, size_t size)
{
void *ptr1;
if (size == 0)
{
free(ptr);
return (NULL);
}
ptr1 = realloc(ptr, size);
if (ptr1 == NULL)
{
fprintf(stderr, "memory full\n");
exit(EXIT_FAILURE);
}
return (ptr1);
}
static TCCReallocFunc *reallocator = default_reallocator;
void
tcc_set_realloc(TCCReallocFunc *my_realloc)
{
if (my_realloc == NULL)
{
reallocator = default_reallocator;
return;
}
reallocator = my_realloc;
}
void
tcc_free(void *ptr)
{
reallocator(ptr, 0);
}
void *
tcc_malloc(size_t size)
{
return (reallocator(NULL, size));
}
void *
tcc_mallocz(size_t size)
{
void *ptr;
ptr = tcc_malloc(size);
if (ptr == NULL)
{
return (NULL);
}
memset(ptr, 0, size);
return (ptr);
}
void *
tcc_realloc(void *ptr, size_t size)
{
return (reallocator(ptr, size));
}
char *
tcc_strdup(const char *str)
{
char *ptr;
ptr = tcc_malloc(strlen(str) + 1);
strcpy(ptr, str);
return (ptr);
}
#ifdef TCC_MEMORY_DEBUG
# define MEMORY_DEBUG_MAGIC1 0xFEEDDEB1
# define MEMORY_DEBUG_MAGIC2 0xFEEDDEB2
# define MEMORY_DEBUG_MAGIC3 0xFEEDDEB3
# define MEMORY_DEBUG_FILE_LEN 40
# define MEMORY_DEBUG_CHECK3(hdr) \
((MemoryDebugHeader *)((uint8_t *)hdr + header->size))->magic3
# define MEMORY_USER_PTR(hdr) \
((uint8_t *)header + offsetof(MemoryDebugHeader, magic3))
# define MEMORY_HEADER_PTR(ptr) \
(MemoryDebugHeader *)((uint8_t *)ptr - offsetof(MemoryDebugHeader, magic3))
typedef struct MemoryDebugHeader {
uint32_t magic1;
size_t size;
struct MemoryDebugHeader *prev;
struct MemoryDebugHeader *next;
int linenum;
char filename[MEMORY_DEBUG_FILE_LEN + 1];
uint32_t magic2;
__attribute__((aligned(16))) uint8_t magic3[4];
} MemoryDebugHeader;
TCC_SEM(static mem_sem);
static MemoryDebugHeader *mem_debug_chain;
static size_t mem_cur_size;
size_t mem_max_size;
static int nb_states;
static MemoryDebugHeader *
malloc_check(void *ptr, const char *msg)
{
MemoryDebugHeader *header;
header = MEMORY_HEADER_PTR(ptr);
if (header->magic1 != MEMORY_DEBUG_MAGIC1
|| header->magic2 != MEMORY_DEBUG_MAGIC2
|| read32le(MEMORY_DEBUG_CHECK3(header)) != MEMORY_DEBUG_MAGIC3
|| header->size == (size_t)-1)
{
fprintf(stderr, "%s check failed\n", msg);
if (header->magic1 == MEMORY_DEBUG_MAGIC1)
{
fprintf(stderr, "%s:%u: block allocated here.\n",
header->filename, header->linenum);
}
exit(EXIT_FAILURE);
}
return (header);
}
void
tcc_free_debug(void *ptr)
{
MemoryDebugHeader *header;
if (ptr == NULL)
{
return;
}
header = malloc_check(ptr, "tcc_free");
WAIT_SEM(&mem_sem);
mem_cur_size -= header->size;
header->size = (size_t)-1;
if (header->next)
{
header->next->prev = header->prev;
}
if (header->prev)
{
header->prev->next = header->next;
}
if (header == mem_debug_chain)
{
mem_debug_chain = header->next;
}
POST_SEM(&mem_sem);
tcc_free(header);
}
void *
tcc_malloc_debug(size_t size, const char *file, int line)
{
int ofs;
MemoryDebugHeader *header;
if (size == 0)
{
return (NULL);
}
header = tcc_malloc(sizeof(MemoryDebugHeader) + size);
header->magic1 = MEMORY_DEBUG_MAGIC1;
header->magic2 = MEMORY_DEBUG_MAGIC2;
header->size = size;
write32le(MEMORY_DEBUG_CHECK3(header), MEMORY_DEBUG_MAGIC3);
header->linenum = line;
ofs = strlen(file) - MEMORY_DEBUG_FILE_LEN;
strncpy(header->filename, file + (ofs > 0 ? ofs : 0), MEMORY_DEBUG_FILE_LEN);
header->filename[MEMORY_DEBUG_FILE_LEN] = 0;
WAIT_SEM(&mem_sem);
header->next = mem_debug_chain;
header->prev = NULL;
if (header->next)
{
header->next->prev = header;
}
mem_debug_chain = header;
mem_cur_size += size;
if (mem_cur_size > mem_max_size)
{
mem_max_size = mem_cur_size;
}
POST_SEM(&mem_sem);
return (MEMORY_USER_PTR(header));
}
void *
tcc_mallocz_debug(size_t size, const char *file, int line)
{
void *ptr;
ptr = tcc_malloc_debug(size, file, line);
if (ptr == NULL)
{
return (NULL);
}
memset(ptr, 0, size);
return (ptr);
}
void *
tcc_realloc_debug(void *ptr, size_t size, const char *file, int line)
{
MemoryDebugHeader *header;
int mem_debug_chain_update;
mem_debug_chain_update = 0;
if (ptr == NULL)
{
return (tcc_malloc_debug(size, file, line));
}
if (size == 0)
{
tcc_free_debug(ptr);
return (NULL);
}
header = malloc_check(ptr, "tcc_realloc");
WAIT_SEM(&mem_sem);
mem_cur_size -= header->size;
mem_debug_chain_update = (header == mem_debug_chain);
header = tcc_realloc(header, sizeof(MemoryDebugHeader) + size);
header->size = size;
write32le(MEMORY_DEBUG_CHECK3(header), MEMORY_DEBUG_MAGIC3);
if (header->next)
{
header->next->prev = header;
}
if (header->prev)
{
header->prev->next = header;
}
if (mem_debug_chain_update)
{
mem_debug_chain = header;
}
mem_cur_size += size;
if (mem_cur_size > mem_max_size)
{
mem_max_size = mem_cur_size;
}
POST_SEM(&mem_sem);
return (MEMORY_USER_PTR(header));
}
char *
tcc_strdup_debug(const char *str, const char *file, int line)
{
char *ptr;
ptr = tcc_malloc_debug(strlen(str) + 1, file, line);
strcpy(ptr, str);
return (ptr);
}
void
tcc_memcheck(int d)
{
MemoryDebugHeader *header;
WAIT_SEM(&mem_sem);
nb_states += d;
if (0 == nb_states && mem_cur_size)
{
header = mem_debug_chain;
fflush(stdout);
fprintf(stderr, "MEM_DEBUG: mem_leak= %d bytes, mem_max_size= %d bytes\n",
mem_cur_size, mem_max_size);
while (header)
{
fprintf(stderr, "%s:%u: error: %u bytes leaked\n",
header->filename, header->linenum, header->size);
header = header->next;
}
fflush(stderr);
mem_cur_size = 0;
mem_max_size = 0;
mem_debug_chain = NULL;
#if TCC_MEMORY_DEBUG-0 == 2
exit(2);
#endif /* TCC_MEMORY_DEBUG == 2 */
}
POST_SEM(&mem_sem);
}
#endif /* TCC_MEMORY_DEBUG */

13
libtcc/object.c Normal file
View file

@ -0,0 +1,13 @@
#include <tcc.h>
#include <tcc/object.h>
#include <tcc/object/archive.h>
#include <tcc/object/coff.h>
int
tcc_object_type(int fd, void *h)
{
size_t size;
return (0);
}

13
libtcc/object/archive.c Normal file
View file

@ -0,0 +1,13 @@
#include <tcc.h>
#include <tcc/object/archive.h>
int
tcc_load_archive(TCCState *s1, int fd, int alacarte)
{
ArchiveFileHeader hdr;
int size;
int len;
size_t file_offset;
return (0);
}

55
libtcc/object/coff.c Normal file
View file

@ -0,0 +1,55 @@
#include <tcc.h>
#include <tcc/object/coff.h>
#define COFF_DEFAULT_ENTRYNAME "_start"
int
tcc_output_coff(TCCState *s1, FILE *f)
{
COFFFileHeader coffhdr;
AOutHeader aouthdr;
COFFSectionHeader coffsec;
const char *entry_name = COFF_DEFAULT_ENTRYNAME;
memset(&coffhdr, 0, sizeof(COFFFileHeader));
coffhdr.flags = COFF_F_LITTLE | COFF_F_LNNO;
coffhdr.magic = COFF_MAGIC;
coffhdr.nscns = s1->nb_sections;
if (s1->output_type == TCC_OUTPUT_EXE)
{
coffhdr.flags |= COFF_F_RELFLG | COFF_F_EXEC | COFF_F_LSYMS;
coffhdr.nsyms = 0;
memset(&aouthdr, 0, sizeof(AOutHeader));
aouthdr.magic = AOUT_ZMAGIC;
coffhdr.opthdr = sizeof(AOutHeader);
if (s1->entryname != NULL)
{
entry_name = s1->entryname;
}
aouthdr.entry = get_sym_addr(s1, entry_name, 1, 0);
if (s1->nb_errors)
{
return (-1);
}
}
return (0);
}
int
coff_output_object(TCCState *s, const char *filename)
{
}
int
coff_output_exe(TCCState *s, const char *filename)
{
}

View file

@ -1,8 +1,13 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif /* HAVE_CONFIG_H */
#include <stdlib.h>
#include <string.h>
#include <tcc.h>
#include <tcc/option.h>
#include <tcc/memory.h>
#include "utils/string.h"
# define F_WD_ALL 0x0001 /* warning is activated when using -Wall */
@ -105,6 +110,7 @@ static const TCCOption options[] = {
{"MMD", OPTION_MMD, 0},
{"MP", OPTION_MP, 0},
{"x", OPTION_x, 0},
{"ar", OPTION_ar, 0},
/* ignored (silently, except after -Wunsupported) */
{"arch", 0, TCC_OPTION_HAS_ARG},
@ -321,20 +327,11 @@ set_linker(TCCState *s, const char *option)
s->nostdlib = 1;
} else if (link_option(option, "e=", &p)
|| link_option(option, "entry=", &p)) {
copy_linker_arg(&s->elf_entryname, p, 0);
} else if (link_option(option, "fini=", &p)) {
copy_linker_arg(&s->fini_symbol, p, 0);
ignoring = 1;
copy_linker_arg(&s->entryname, p, 0);
} else if (link_option(option, "image-base=", &p)
|| link_option(option, "Ttext=", &p)) {
s->text_addr = strtoull(p, &end, 16);
s->has_text_addr = 1;
} else if (link_option(option, "init=", &p)) {
copy_linker_arg(&s->init_symbol, p, 0);
ignoring = 1;
} else if (link_option(option, "Map=", &p)) {
copy_linker_arg(&s->mapfile, p, 0);
ignoring = 1;
} else if (link_option(option, "oformat=", &p)) {
if (strstart("elf32-", &p)) {
s->output_format = TCC_OUTPUT_FORMAT_ELF;

47
libtcc/path.c Normal file
View file

@ -0,0 +1,47 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif /* HAVE_CONFIG_H */
#ifdef HAVE_LIBGEN_H
# include <libgen.h>
#endif /* HAVE_LIBGEN_H */
#include <string.h>
#include <tcc/path.h>
/* extract the basename of a file */
char *
tcc_basename(const char *name)
{
#ifdef HAVE_LIBGEN_H
return (basename((char *)name));
#else
char *p;
p = strchr(name, 0);
while (p > name && !IS_DIRSEP(p[-1]))
{
--p;
}
return (p);
#endif /* HAVE_LIBGEN_H */
}
/* extract extension part of a file
*
* (if no extension, return pointer to end-of-string)
*/
char *
tcc_fileextension(const char *name)
{
const char *b;
char *e;
b = tcc_basename(name);
e = strrchr(tcc_basename(name), '.');
if (e)
{
return (e);
}
return (strchr(b, 0));
}

View file

@ -1,4 +0,0 @@
#ifndef TCC_INTERNAL_H
# define TCC_INTERNAL_H 1
#endif /* !TCC_INTERNAL_H */

View file

@ -1,4 +1,10 @@
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif /* HAVE_CONFIG_H */
#include <tcc.h>
#include <tcc/path.h>
#include <tcc/memory.h>
static int
read_mem(int fd, unsigned offset, void *buffer, unsigned len)
@ -99,7 +105,8 @@ coff_load_file(TCCState *s1, int fd, const char *fname)
}
int
coff_output_file(TCCState *s1, const char *fname)
coff_output_file(TCCState *s1, const char *filename)
{
return (0);
}

View file

@ -18,7 +18,13 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif /* HAVE_CONFIG_H */
#include <tcc.h>
#include <tcc/path.h>
#include <tcc/memory.h>
#include "utils/string.h"
@ -473,12 +479,7 @@ addr_t get_sym_addr(TCCState *s1, const char *name, int err, int forc)
int sym_index;
ElfW(Sym) *sym;
char buf[256];
if (forc && s1->leading_underscore
#ifdef TCC_TARGET_PE
/* win32-32bit stdcall symbols always have _ already */
&& !strchr(name, '@')
#endif
) {
if (forc && s1->leading_underscore) {
buf[0] = '_';
pstrcpy(buf + 1, sizeof(buf) - 1, name);
name = buf;
@ -1872,8 +1873,8 @@ static int tcc_output_elf(TCCState *s1, FILE *f, int phnum, ElfW(Phdr) *phdr)
ehdr.e_type = ET_REL;
} else {
ehdr.e_type = ET_EXEC;
if (s1->elf_entryname)
ehdr.e_entry = get_sym_addr(s1, s1->elf_entryname, 1, 0);
if (s1->entryname)
ehdr.e_entry = get_sym_addr(s1, s1->entryname, 1, 0);
else
ehdr.e_entry = get_sym_addr(s1, "_start", !!(file_type & TCC_OUTPUT_EXE), 0);
if (ehdr.e_entry == (addr_t)-1)

View file

@ -18,8 +18,14 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif /* HAVE_CONFIG_H */
#define USING_GLOBALS
#include <tcc.h>
#include <tcc/memory.h>
#include "utils/string.h"
#include "token.h"

View file

@ -18,8 +18,14 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif /* HAVE_CONFIG_H */
#define USING_GLOBALS
#include <tcc.h>
#include <tcc/path.h>
#include <tcc/memory.h>
#include "utils/string.h"
#include "token.h"
#include <math.h>
@ -127,12 +133,12 @@ void expect(const char *msg)
#define tal_new(a,b,c)
#define tal_delete(a)
#else
#if !defined(MEM_DEBUG)
#if !defined(TCC_MEMORY_DEBUG)
#define tal_free(al, p) tal_free_impl(al, p)
#define tal_realloc(al, p, size) tal_realloc_impl(&al, p, size)
#define TAL_DEBUG_PARAMS
#else
#define TAL_DEBUG MEM_DEBUG
#define TAL_DEBUG TCC_MEMORY_DEBUG
//#define TAL_INFO 1 /* collect and dump allocators stats */
#define tal_free(al, p) tal_free_impl(al, p, __FILE__, __LINE__)
#define tal_realloc(al, p, size) tal_realloc_impl(&al, p, size, __FILE__, __LINE__)

View file

@ -4,6 +4,10 @@ noinst_LIBRARIES = libtcc1.a
libtcc1_a_SOURCES = alloca.S atomic.S builtin.c libtcc1.c stdatomic.c
libtcc1_a_AR = ../tcc/tcc -ar cr
libtcc1_a_DEPENDENCIES = ../tcc/tcc
libtcc1_a_RANLIB = @echo
alloca.o: alloca.S
$(COMPILE) -o $@ -c $^ -I$(srcdir)/include

View file

@ -24,6 +24,8 @@
#include <tcc.h>
#include <tcc/option.h>
#include <tcc/path.h>
#include <tcc/memory.h>
#include "tcctools.h"
static const char help_str[] =

View file

@ -28,9 +28,10 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "tcc.h"
#include <tcc.h>
#include <tcc/path.h>
#include <tcc/object/archive.h>
#include <tcc/memory.h>
static unsigned long le2belong(unsigned long ul) {
return ((ul & 0xFF0000)>>8)+((ul & 0xFF000000)>>24) +