Compare commits

...

10 Commits

Author SHA1 Message Date
Bernhard Reutner-Fischer bfa394dab8 Move bounds-checking code to a bcheck.a
... to avoid undefined references to __bound_new_region()
(when using a libtcc1_s.so instead of libtcc1.a) on i386.

Signed-off-by: aldot <rep.dot.nop@gmail.com>
2009-12-01 17:59:36 +01:00
Bernhard Reutner-Fischer a39d055d0e Handle --whole-archive
Support and document -Wl,--{no-,}whole-archive.

Signed-off-by: aldot <rep.dot.nop@gmail.com>
2009-12-01 17:59:35 +01:00
Bernhard Reutner-Fischer f0e8b23d02 Implement -m{uclibc,glibc} to choose elf_interp
Support -muclibc and -mglibc (default) to choose between the elf
  interpreter like gcc does.

  $ ./tcc -o hi-glibc hello.c
  $ ./tcc -muclibc -o hi-uclibc hello.c
  $ readelf -l hi-* | egrep "(^File: | interpreter)"
File: hi-glibc
      [Requesting program interpreter: /lib/ld-linux.so.2]
File: hi-uclibc
      [Requesting program interpreter: /lib/ld-uClibc.so.0]

Signed-off-by: aldot <rep.dot.nop@gmail.com>
2009-12-01 17:59:35 +01:00
Bernhard Reutner-Fischer 83cb1364a6 Revert "add --enable-shared, part1"
This reverts commit 9257c5221ea4f095d813082716f786c6c5d23321.

Signed-off-by: aldot <rep.dot.nop@gmail.com>
2009-12-01 17:59:34 +01:00
Bernhard Reutner-Fischer d90eb2008b add --enable-shared, part1
Build a libtcc.so and link the tcc binary against it.

Signed-off-by: aldot <rep.dot.nop@gmail.com>
2009-12-01 17:59:33 +01:00
Bernhard Reutner-Fischer 8a555345e3 warn about incorrect use of output_*
Signed-off-by: aldot <rep.dot.nop@gmail.com>
2009-12-01 17:59:33 +01:00
Bernhard Reutner-Fischer 3a40b44938 allow for non-stripped install
Signed-off-by: aldot <rep.dot.nop@gmail.com>
2009-12-01 17:59:32 +01:00
Mitchell N Charity 77999caefe Fix the script for generating tcc.h symbol prefix #defines.
It no longer incorrectly adds a _tcc_ prefix to symbols which already have it.
2009-12-01 17:59:32 +01:00
Mitchell N Charity e78212e2af Fix libtcc symbol namespace pollution and user conflicts.
All defined global symbols now have either a tcc_ (public api) or _tcc_ prefix.
(There had been 80+ unprefixed global symbols defined in libtcc).
This should resolve the reported link failures due to "error()" conflicts.
2009-12-01 17:59:31 +01:00
Mitchell N Charity a5db5cf8df Check getcwd() return value for error. Thus silencing a gcc warning. 2009-12-01 17:59:30 +01:00
7 changed files with 207 additions and 58 deletions

View File

@ -8,6 +8,7 @@ include $(TOP)/config.mak
CFLAGS+=-g -Wall
CFLAGS_P=$(CFLAGS) -pg -static -DCONFIG_TCC_STATIC
LIBS_P=
CFLAGS_PIC ?= -fPIC
ifneq ($(GCC_MAJOR),2)
CFLAGS+=-fno-strict-aliasing
@ -32,19 +33,23 @@ LIBS+=-ldl
endif
endif
BCHECK=
BCHECK_O=
ALLOCA_O=
ifeq ($(ARCH),i386)
NATIVE_TARGET=-DTCC_TARGET_I386
LIBTCC1=libtcc1.a
BCHECK_O=bcheck.o
ALLOCA_O=alloca86.o alloca86-bt.o
else
ALLOCA_O=alloca86.o
BCHECK_O=bcheck.o alloca86-bt.o
BCHECK=bcheck.a
endif
ifeq ($(ARCH),x86-64)
NATIVE_TARGET=-DTCC_TARGET_X86_64
LIBTCC1=libtcc1.a
BCHECK_O=
ALLOCA_O=alloca86_64.o
endif
endif
ifeq ($(ARCH),arm)
NATIVE_TARGET=-DTCC_TARGET_ARM
@ -54,12 +59,10 @@ endif
ifdef CONFIG_WIN32
NATIVE_TARGET+=-DTCC_TARGET_PE
BCHECK_O=
endif
ifneq ($(wildcard /lib/ld-uClibc.so.0),)
NATIVE_TARGET+=-DTCC_UCLIBC
BCHECK_O=
endif
ifdef CONFIG_USE_LIBGCC
@ -113,7 +116,7 @@ ifdef CONFIG_CROSS
PROGS+=$(PROGS_CROSS)
endif
all: $(PROGS) $(LIBTCC1) $(BCHECK_O) libtcc.a tcc-doc.html tcc.1 libtcc_test$(EXESUF)
all: $(PROGS) $(LIBTCC1) $(BCHECK) libtcc.a tcc-doc.html tcc.1 libtcc_test$(EXESUF)
# Host Tiny C Compiler
tcc$(EXESUF): $(NATIVE_FILES)
@ -196,14 +199,17 @@ libtcc1.a: $(LIBTCC1_OBJS)
bcheck.o: bcheck.c
$(CC) -o $@ -c $< -O2 -Wall
bcheck.a: $(BCHECK_O)
$(AR) rcs $@ $^
# install
TCC_INCLUDES = stdarg.h stddef.h stdbool.h float.h varargs.h tcclib.h
INSTALL=install
ifndef CONFIG_WIN32
install: $(PROGS) $(LIBTCC1) $(BCHECK_O) libtcc.a tcc.1 tcc-doc.html
install: $(PROGS) $(LIBTCC1) $(BCHECK) libtcc.a tcc.1 tcc-doc.html
mkdir -p "$(bindir)"
$(INSTALL) -s -m755 $(PROGS) "$(bindir)"
$(INSTALL) -m755 $(PROGS) "$(bindir)"
mkdir -p "$(mandir)/man1"
$(INSTALL) tcc.1 "$(mandir)/man1"
mkdir -p "$(tccdir)"
@ -211,8 +217,8 @@ install: $(PROGS) $(LIBTCC1) $(BCHECK_O) libtcc.a tcc.1 tcc-doc.html
ifneq ($(LIBTCC1),)
$(INSTALL) -m644 $(LIBTCC1) "$(tccdir)"
endif
ifneq ($(BCHECK_O),)
$(INSTALL) -m644 $(BCHECK_O) "$(tccdir)"
ifneq ($(BCHECK),)
$(INSTALL) -m644 $(BCHECK) "$(tccdir)"
endif
$(INSTALL) -m644 $(addprefix include/,$(TCC_INCLUDES)) "$(tccdir)/include"
mkdir -p "$(docdir)"
@ -224,20 +230,20 @@ endif
uninstall:
rm -fv $(foreach P,$(PROGS),"$(bindir)/$P")
rm -fv $(foreach P,$(LIBTCC1) $(BCHECK_O),"$(tccdir)/$P")
rm -fv $(foreach P,$(LIBTCC1) $(BCHECK),"$(tccdir)/$P")
rm -fv $(foreach P,$(TCC_INCLUDES),"$(tccdir)/include/$P")
rm -fv "$(docdir)/tcc-doc.html" "$(mandir)/man1/tcc.1"
rm -fv "$(libdir)/libtcc.a" "$(includedir)/libtcc.h"
else
install: $(PROGS) $(LIBTCC1) libtcc.a tcc-doc.html
mkdir -p "$(tccdir)"
mkdir -p "$(bindir)"
mkdir -p "$(tccdir)/lib"
mkdir -p "$(tccdir)/include"
mkdir -p "$(tccdir)/examples"
mkdir -p "$(tccdir)/doc"
mkdir -p "$(tccdir)/libtcc"
$(INSTALL) -s -m755 $(PROGS) "$(tccdir)"
$(INSTALL) -m755 $(PROGS) "$(bindir)"
$(INSTALL) -m644 $(LIBTCC1) win32/lib/*.def "$(tccdir)/lib"
cp -r win32/include/. "$(tccdir)/include"
cp -r win32/examples/. "$(tccdir)/examples"
@ -245,6 +251,10 @@ install: $(PROGS) $(LIBTCC1) libtcc.a tcc-doc.html
$(INSTALL) -m644 tcc-doc.html win32/tcc-win32.txt "$(tccdir)/doc"
$(INSTALL) -m644 libtcc.a libtcc.h "$(tccdir)/libtcc"
endif
install-strip: install
ifneq ($(strip $(STRIP)),)
$(STRIP) $(addprefix $(bindir), $(PROGS))
endif
# documentation and man page
tcc-doc.html: tcc-doc.texi

View File

@ -206,6 +206,7 @@ static int tcc_add_dll(TCCState *s, const char *filename, int flags);
#define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
#define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
#define AFF_PREPROCESS 0x0004 /* preprocess file */
#define AFF_WHOLE_ARCHIVE 0x0008 /* add whole archive not just undef symbol */
static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
/* tcccoff.c */
@ -1247,7 +1248,8 @@ static int tcc_compile(TCCState *s1)
section_sym = put_elf_sym(symtab_section, 0, 0,
ELFW(ST_INFO)(STB_LOCAL, STT_SECTION), 0,
text_section->sh_num, NULL);
getcwd(buf, sizeof(buf));
if (getcwd(buf, sizeof(buf)) == NULL)
error("getcwd: %s",strerror(errno));
#ifdef _WIN32
normalize_slashes(buf);
#endif
@ -2116,7 +2118,7 @@ static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
file->line_num = 0; /* do not display line number if error */
ret = tcc_load_archive(s1, fd);
ret = tcc_load_archive(s1, fd, flags & AFF_WHOLE_ARCHIVE);
goto the_end;
}
@ -2133,9 +2135,11 @@ static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
/* as GNU ld, consider it is an ld script if not recognized */
ret = tcc_load_ldscript(s1);
#endif
/* TODO: the_end label should be here !! */
if (ret < 0)
error_noabort("unrecognized file type");
error_noabort("%s: unrecognized file type", filename);
else if (s1->verbose)
printf("+> %s\n", filename);
the_end:
if (file)
tcc_close(file);
@ -2211,7 +2215,7 @@ int tcc_add_symbol(TCCState *s, const char *name, void *val)
return 0;
}
int tcc_set_output_type(TCCState *s, int output_type)
int tcc_set_output_type(TCCState *s, output_t output_type)
{
char buf[1024];

View File

@ -61,17 +61,23 @@ LIBTCCAPI int tcc_compile_string(TCCState *s, const char *buf);
/* linking commands */
/* set output type. MUST BE CALLED before any compilation */
#define TCC_OUTPUT_MEMORY 0 /* output will be ran in memory (no
enum output_type_e {
TCC_OUTPUT_MEMORY = 0, /* output will be ran in memory (no
output file) (default) */
#define TCC_OUTPUT_EXE 1 /* executable file */
#define TCC_OUTPUT_DLL 2 /* dynamic library */
#define TCC_OUTPUT_OBJ 3 /* object file */
#define TCC_OUTPUT_PREPROCESS 4 /* preprocessed file (used internally) */
LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type);
TCC_OUTPUT_EXE = 1, /* executable file */
TCC_OUTPUT_DLL = 2, /* dynamic library */
TCC_OUTPUT_OBJ = 3, /* object file */
TCC_OUTPUT_PREPROCESS = 4 /* preprocessed file (used internally) */
};
typedef enum output_type_e output_t;
LIBTCCAPI int tcc_set_output_type(TCCState *s, output_t output_type);
#define TCC_OUTPUT_FORMAT_ELF 0 /* default output format: ELF */
#define TCC_OUTPUT_FORMAT_BINARY 1 /* binary image output */
#define TCC_OUTPUT_FORMAT_COFF 2 /* COFF */
enum output_format_e {
TCC_OUTPUT_FORMAT_ELF = 0, /* default output format: ELF */
TCC_OUTPUT_FORMAT_BINARY = 1, /* binary image output */
TCC_OUTPUT_FORMAT_COFF = 2 /* COFF */
};
typedef enum output_format_e output_format_t;
/* equivalent to -Lpath option */
LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname);

View File

@ -299,6 +299,14 @@ also be given).
@item -Wl,-Ttext,address
Set the start of the .text section to @var{address}.
@item -Wl,--whole-archive
Add a whole archive, not just the symbols of the archive that would
satisfy undefined symbols in the program.
@item -Wl,--no-whole-archive
Turn off the effect of the --whole-archive option for subsequent archive
files.
@item -Wl,--oformat,fmt
Use @var{fmt} as output format. The supported output formats are:
@table @code
@ -332,8 +340,8 @@ Display N callers in stack traces. This is useful with @option{-g} or
@end table
Note: GCC options @option{-Ox}, @option{-fx} and @option{-mx} are
ignored.
Note: GCC options @option{-Ox}, @option{-fx} and @option{-mx} are ignored
except @option{-muclibc} and @option{-mglibc}.
@c man end
@ignore

24
tcc.c
View File

@ -54,6 +54,8 @@ void help(void)
" -static static linking\n"
" -rdynamic export all global symbols to dynamic linker\n"
" -r generate (relocatable) object file\n"
" --whole-archive include all object files in the archives\n"
" --no-whole-archive turn the effect of --whole-archives off\n"
"Debugger options:\n"
" -g generate runtime debug info\n"
#ifdef CONFIG_TCC_BCHECK
@ -66,13 +68,15 @@ void help(void)
}
static char **files;
static int nb_files, nb_libraries;
static char **whole_archives;
static int nb_files, nb_libraries, nb_whole_archive;
static int multiple_files;
static int print_search_dirs;
static int output_type;
static output_t output_type;
static int reloc_output;
static const char *outfile;
static int do_bench = 0;
static unsigned do_whole_archive = 0;
#define TCC_OPTION_HAS_ARG 0x0001
#define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
@ -227,6 +231,7 @@ int parse_args(TCCState *s, int argc, char **argv)
if (r[0] != '-' || r[1] == '\0') {
/* add a new file */
dynarray_add((void ***)&files, &nb_files, r);
dynarray_add((void ***)&whole_archives, &nb_whole_archive, (void*)do_whole_archive);
if (!multiple_files) {
optind--;
/* argv[0] will be this file */
@ -297,6 +302,7 @@ int parse_args(TCCState *s, int argc, char **argv)
break;
case TCC_OPTION_l:
dynarray_add((void ***)&files, &nb_files, r);
dynarray_add((void ***)&whole_archives, &nb_whole_archive, (void*)do_whole_archive);
nb_libraries++;
break;
case TCC_OPTION_bench:
@ -442,6 +448,10 @@ int parse_args(TCCState *s, int argc, char **argv)
{
error("target %s not found", p);
}
} else if (strstart(optarg, "--whole-archive", &p)) {
do_whole_archive = 1;
} else if (strstart(optarg, "--no-whole-archive", &p)) {
do_whole_archive = 0;
} else {
error("unsupported linker option '%s'", optarg);
}
@ -452,6 +462,9 @@ int parse_args(TCCState *s, int argc, char **argv)
break;
case TCC_OPTION_x:
break;
case TCC_OPTION_m:
s->use_ulibc_interp = !strcmp("uclibc", optarg);
break;
default:
if (s->warn_unsupported) {
unsupported_option:
@ -478,8 +491,10 @@ int main(int argc, char **argv)
outfile = NULL;
multiple_files = 1;
files = NULL;
whole_archives = NULL;
nb_files = 0;
nb_libraries = 0;
nb_whole_archive = 0;
reloc_output = 0;
print_search_dirs = 0;
ret = 0;
@ -563,9 +578,10 @@ int main(int argc, char **argv)
ret = 1;
}
} else {
int whole = ((int)whole_archives[i]) << 3; /* AFF_WHOLE_ARCHIVE */
if (1 == s->verbose)
printf("-> %s\n", filename);
if (tcc_add_file(s, filename) < 0)
printf("-%c %s\n", whole?'[':'>', filename);
if (tcc_add_file_internal(s, filename, whole) < 0)
ret = 1;
}
}

107
tcc.h
View File

@ -108,7 +108,7 @@
#define TCC_TARGET_I386
#endif
#if !defined(_WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
#if !defined(_WIN32) && !defined(TCC_TARGET_ARM) && \
!defined(TCC_TARGET_C67) && !defined(TCC_TARGET_X86_64)
#define CONFIG_TCC_BCHECK /* enable bound checking code */
#endif
@ -392,8 +392,8 @@ typedef struct ASMOperand {
#endif
struct TCCState {
int output_type;
output_t output_type;
BufferedFile **include_stack_ptr;
int *ifdef_stack_ptr;
@ -454,7 +454,7 @@ struct TCCState {
int has_text_addr;
/* output format, see TCC_OUTPUT_FORMAT_xxx */
int output_format;
output_format_t output_format;
/* C language options */
int char_is_unsigned;
@ -531,6 +531,7 @@ struct TCCState {
unsigned int runtime_plt_and_got_offset;
#endif
#endif
unsigned int use_ulibc_interp; /* elf-interpreter to use */
};
/* The current value can be: */
@ -762,8 +763,7 @@ enum tcc_token {
#define strtof (float)strtod
#define strtoll (long long)strtol
#endif
#elif defined(TCC_UCLIBC) || defined(__FreeBSD__) || defined(__DragonFly__) \
|| defined(__OpenBSD__)
#elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
/* currently incorrect */
long double strtold(const char *nptr, char **endptr)
{
@ -789,6 +789,101 @@ extern long double strtold (const char *__nptr, char **__endptr);
#define PATHCMP strcmp
#endif
/* impose symbol hygiene
All global symbols defined in libtcc.a should have a prefix of either
tcc_ or _tcc_ , to avoid user namespace pollution and conflicts.
nm -g -P libtcc.a |perl -e '$x=<>;while(<>){my($symbol,$type)=/(\S+) (\S) / or die;next if $type eq "U"||$symbol=~/^_?tcc_/;print "#define $symbol _tcc_$symbol\n"}' > insert_below
*/
#define bn_lshift _tcc_bn_lshift
#define bn_zero _tcc_bn_zero
#define dynarray_add _tcc_dynarray_add
#define dynarray_reset _tcc_dynarray_reset
#define elf_output_file _tcc_elf_output_file
#define error _tcc_error
#define error1 _tcc_error1
#define error_noabort _tcc_error_noabort
#define expect _tcc_expect
#define find_section _tcc_find_section
#define force_charshort_cast _tcc_force_charshort_cast
#define g _tcc_g
#define gaddrof _tcc_gaddrof
#define gen_cvt_ftof _tcc_gen_cvt_ftof
#define gen_cvt_ftoi _tcc_gen_cvt_ftoi
#define gen_cvt_ftoi1 _tcc_gen_cvt_ftoi1
#define gen_cvt_itof _tcc_gen_cvt_itof
#define gen_cvt_itof1 _tcc_gen_cvt_itof1
#define gen_le32 _tcc_gen_le32
#define gen_le64 _tcc_gen_le64
#define gen_op _tcc_gen_op
#define gen_opf _tcc_gen_opf
#define gen_opi _tcc_gen_opi
#define gen_opic _tcc_gen_opic
#define gen_opif _tcc_gen_opif
#define gen_opl _tcc_gen_opl
#define get_reg _tcc_get_reg
#define get_reg_ex _tcc_get_reg_ex
#define get_tok_str _tcc_get_tok_str
#define gfunc_call _tcc_gfunc_call
#define gfunc_epilog _tcc_gfunc_epilog
#define gfunc_prolog _tcc_gfunc_prolog
#define ggoto _tcc_ggoto
#define gjmp _tcc_gjmp
#define gjmp_addr _tcc_gjmp_addr
#define gsym _tcc_gsym
#define gsym_addr _tcc_gsym_addr
#define gtst _tcc_gtst
#define gv _tcc_gv
#define gv2 _tcc_gv2
#define gv_dup _tcc_gv_dup
#define ieee_finite _tcc_ieee_finite
#define inc _tcc_inc
#define lbuild _tcc_lbuild
#define lexpand _tcc_lexpand
#define load _tcc_load
#define move_reg _tcc_move_reg
#define new_section _tcc_new_section
#define num_callers _tcc_num_callers
#define o _tcc_o
#define parse_number _tcc_parse_number
#define preprocess_new _tcc_preprocess_new
#define preprocess_skip _tcc_preprocess_skip
#define pstrcat _tcc_pstrcat
#define pstrcpy _tcc_pstrcpy
#define put_func_debug _tcc_put_func_debug
#define rc_fret _tcc_rc_fret
#define reg_classes _tcc_reg_classes
#define reg_fret _tcc_reg_fret
#define resolve_sym _tcc_resolve_sym
#define restore_parse_state _tcc_restore_parse_state
#define rt_bound_error_msg _tcc_rt_bound_error_msg
#define rt_error _tcc_rt_error
#define rt_prog_main _tcc_rt_prog_main
#define save_parse_state _tcc_save_parse_state
#define save_reg _tcc_save_reg
#define save_regs _tcc_save_regs
#define set_pages_executable _tcc_set_pages_executable
#define skip _tcc_skip
#define store _tcc_store
#define swap _tcc_swap
#define total_bytes _tcc_total_bytes
#define total_lines _tcc_total_lines
#define type_to_str _tcc_type_to_str
#define vdup _tcc_vdup
#define vpop _tcc_vpop
#define vpushi _tcc_vpushi
#define vpushll _tcc_vpushll
#define vpushv _tcc_vpushv
#define vrotb _tcc_vrotb
#define vrott _tcc_vrott
#define vset _tcc_vset
#define vsetc _tcc_vsetc
#define vseti _tcc_vseti
#define vstore _tcc_vstore
#define vswap _tcc_vswap
#define warning _tcc_warning
void error(const char *fmt, ...);
void error_noabort(const char *fmt, ...);
void warning(const char *fmt, ...);

View File

@ -1207,8 +1207,8 @@ static void tcc_add_runtime(TCCState *s1)
ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
bounds_section->sh_num, "__bounds_start");
/* add bound check code */
snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "bcheck.o");
tcc_add_file(s1, buf);
snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, "bcheck.a");
tcc_add_file_internal(s1, buf, AFF_WHOLE_ARCHIVE | AFF_PRINT_ERROR);
#ifdef TCC_TARGET_I386
if (s1->output_type != TCC_OUTPUT_MEMORY) {
/* add 'call __bound_init()' in .init section */
@ -1301,17 +1301,21 @@ static void tcc_add_linker_symbols(TCCState *s1)
}
/* name of ELF interpreter */
static const char elf_interp[] =
#if defined __FreeBSD__
static const char elf_interp[] = "/libexec/ld-elf.so.1";
"/libexec/ld-elf.so.1";
#elif defined TCC_ARM_EABI
static const char elf_interp[] = "/lib/ld-linux.so.3";
"/lib/ld-linux.so.3"
#elif defined(TCC_TARGET_X86_64)
static const char elf_interp[] = "/lib/ld-linux-x86-64.so.2";
#elif defined(TCC_UCLIBC)
static const char elf_interp[] = "/lib/ld-uClibc.so.0";
"/lib/ld-linux-x86-64.so.2"
#else
static const char elf_interp[] = "/lib/ld-linux.so.2";
"/lib/ld-linux.so.2"
#endif
#if 1
"\0/lib/ld-uClibc.so.0"
#endif
"\0"
;
static void tcc_output_binary(TCCState *s1, FILE *f,
const int *section_order)
@ -1405,16 +1409,19 @@ int elf_output_file(TCCState *s1, const char *filename)
ElfW(Sym) *esym, *sym_end;
if (file_type == TCC_OUTPUT_EXE) {
/* add interpreter section only if executable */
const char *ld = elf_interp;
const char *ld_env = getenv("LD_SO");
char *ptr;
/* allow override the dynamic loader */
const char *elfint = getenv("LD_SO");
if (elfint == NULL)
elfint = elf_interp;
/* add interpreter section only if executable */
if (s1->use_ulibc_interp == 1)
ld += strlen(ld) + 1;
else if (ld_env)
ld = ld_env;
interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
interp->sh_addralign = 1;
ptr = section_ptr_add(interp, 1+strlen(elfint));
strcpy(ptr, elfint);
ptr = section_ptr_add(interp, 1+strlen(ld));
strcpy(ptr, ld);
}
/* add dynamic symbol table */
@ -2418,7 +2425,7 @@ static int get_be32(const uint8_t *b)
}
/* load only the objects which resolve undefined symbols */
static int tcc_load_alacarte(TCCState *s1, int fd, int size)
static int tcc_load_alacarte(TCCState *s1, int fd, int size, int whole_archive)
{
int i, bound, nsyms, sym_index, off, ret;
uint8_t *data;
@ -2440,6 +2447,7 @@ static int tcc_load_alacarte(TCCState *s1, int fd, int size)
if(sym_index) {
sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
if(sym->st_shndx == SHN_UNDEF) {
load_obj:
off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
#if 0
printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
@ -2452,6 +2460,8 @@ static int tcc_load_alacarte(TCCState *s1, int fd, int size)
goto the_end;
}
}
} else if (whole_archive) {
goto load_obj;
}
}
} while(bound);
@ -2462,7 +2472,7 @@ static int tcc_load_alacarte(TCCState *s1, int fd, int size)
}
/* load a '.a' file */
static int tcc_load_archive(TCCState *s1, int fd)
static int tcc_load_archive(TCCState *s1, int fd, int whole_archive)
{
ArchiveHeader hdr;
char ar_size[11];
@ -2498,7 +2508,7 @@ static int tcc_load_archive(TCCState *s1, int fd)
if (!strcmp(ar_name, "/")) {
/* coff symbol table : we handle it */
if(s1->alacarte_link)
return tcc_load_alacarte(s1, fd, size);
return tcc_load_alacarte(s1, fd, size, whole_archive);
} else if (!strcmp(ar_name, "//") ||
!strcmp(ar_name, "__.SYMDEF") ||
!strcmp(ar_name, "__.SYMDEF/") ||