From 19a169ceb896f78205bc23b847938c58f14d1dda Mon Sep 17 00:00:00 2001 From: seyko Date: Fri, 20 May 2016 15:12:32 +0300 Subject: [PATCH] --whole-archive support A patch is implemented as suggested in tinycc-devel mail list. From: Reuben Thomas Date: Thu, 31 Jul 2014 16:52:53 +0100 Subject: [PATCH] Add --{no,}-whole-archive support I resurrected the patch supplied to the mailing list in 2009 Since --whole-archive is a useful flag to get tcc working with autotools, and of course in its own right, I suggest you have a look at the patch and see if it is acceptable. I cannot see any suggestion that it was actively rejected last time round, just no evidence that it was ever added. --- libtcc.c | 14 +++++++++++++- libtcc.h | 2 ++ tcc-doc.texi | 8 ++++++++ tcc.c | 18 ++++++++++++++++-- tcc.h | 1 + tccelf.c | 3 +++ 6 files changed, 43 insertions(+), 3 deletions(-) diff --git a/libtcc.c b/libtcc.c index b0fcdf9f..a39bd5ff 100644 --- a/libtcc.c +++ b/libtcc.c @@ -1406,9 +1406,11 @@ ST_FUNC int tcc_add_file_internal(TCCState *s1, const char *filename, int flags, ret = tcc_load_ldscript(s1); #endif if (ret < 0) - tcc_error_noabort("unrecognized file type"); + tcc_error_noabort("%s: unrecognized file type (error=%d)", filename, ret); the_end: + if (s1->verbose) + printf("+> %s\n", filename); tcc_close(); return ret; } @@ -2306,6 +2308,16 @@ ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv) s->rdynamic = 1; break; case TCC_OPTION_Wl: + if (optarg && *optarg == '-') { + int offs = 0; + if (!strncmp("-no", optarg+1, 3)) + offs += 3; + if (!strcmp("-whole-archive", optarg+1 + offs)) { + args_parser_add_file(s, "", (offs == 0) ? TCC_FILETYPE_AR_WHOLE_ON : + TCC_FILETYPE_AR_WHOLE_OFF); + break; + } + } if (pas->linker_arg.size) --pas->linker_arg.size, cstr_ccat(&pas->linker_arg, ','); cstr_cat(&pas->linker_arg, optarg, 0); diff --git a/libtcc.h b/libtcc.h index 97b85872..8f39d195 100644 --- a/libtcc.h +++ b/libtcc.h @@ -53,6 +53,8 @@ LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename, int filetype); #define TCC_FILETYPE_C 2 #define TCC_FILETYPE_ASM 3 #define TCC_FILETYPE_ASM_PP 4 +#define TCC_FILETYPE_AR_WHOLE_OFF 5 +#define TCC_FILETYPE_AR_WHOLE_ON 6 /* compile a string containing a C source. Return -1 if error. */ LIBTCCAPI int tcc_compile_string(TCCState *s, const char *buf); diff --git a/tcc-doc.texi b/tcc-doc.texi index 4e26489f..38b1f747 100644 --- a/tcc-doc.texi +++ b/tcc-doc.texi @@ -317,6 +317,14 @@ Generate an object file combining all input files. @item -Wl,-rpath=path Put custom seatch path for dynamic libraries into executable. +@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 diff --git a/tcc.c b/tcc.c index b340d9bd..5e0a64a1 100644 --- a/tcc.c +++ b/tcc.c @@ -247,6 +247,13 @@ static int64_t getclock_us(void) #endif } +static void set_whole_archive(TCCState* s, int on) +{ + s->whole_archive = on; + if (1 == s->verbose) + printf("%cwhole-archive>\n", s->whole_archive? '+' : '-'); +} + int main(int argc, char **argv) { TCCState *s; @@ -301,6 +308,14 @@ int main(int argc, char **argv) for(i = ret = 0; i < s->nb_files && ret == 0; i++) { int filetype = *(unsigned char *)s->files[i]; const char *filename = s->files[i] + 1; + if (filetype == TCC_FILETYPE_AR_WHOLE_ON || + filetype == TCC_FILETYPE_AR_WHOLE_OFF) + { + set_whole_archive(s, filetype == TCC_FILETYPE_AR_WHOLE_ON); + continue; + } + if (1 == s->verbose) + printf("-> %s\n", filename); if (filename[0] == '-' && filename[1] == 'l') { if (tcc_add_library(s, filename + 2) < 0) { /* don't fail on -lm as it's harmless to skip math lib */ @@ -310,8 +325,6 @@ int main(int argc, char **argv) } } } else { - if (1 == s->verbose) - printf("-> %s\n", filename); if (!s->outfile) s->outfile = default_outputfile(s, filename); if (tcc_add_file(s, filename, filetype) < 0) @@ -335,6 +348,7 @@ int main(int argc, char **argv) } } } + set_whole_archive(s, 0); if (0 == ret) { if (s->output_type == TCC_OUTPUT_MEMORY) { diff --git a/tcc.h b/tcc.h index 7b4481e6..78d0b2df 100644 --- a/tcc.h +++ b/tcc.h @@ -692,6 +692,7 @@ struct TCCState { int rdynamic; /* if true, all symbols are exported */ int symbolic; /* if true, resolve symbols in the current module first */ int alacarte_link; /* if true, only link in referenced objects from archive */ + int whole_archive; /* if true, link in a whole *.a even when alacarte_link */ char *tcc_lib_path; /* CONFIG_TCCDIR or -B option */ char *soname; /* as specified on the command line (-soname) */ diff --git a/tccelf.c b/tccelf.c index 1ef4aef2..2b50ff52 100644 --- a/tccelf.c +++ b/tccelf.c @@ -3076,6 +3076,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); ++bound; lseek(fd, off, SEEK_SET); @@ -3085,6 +3086,8 @@ static int tcc_load_alacarte(TCCState *s1, int fd, int size) goto the_end; } } + } else if (s1->whole_archive) { + goto load_obj; } } } while(bound); -- 2.11.4.GIT