diff options
| author | grischka <grischka> | 2016-10-01 21:58:23 +0200 |
|---|---|---|
| committer | grischka <grischka> | 2016-10-01 22:01:33 +0200 |
| commit | e03306d1709d13d2e67349d42488a93abc4dc32a (patch) | |
| tree | 3f5d14a60f3b4589a3f418110ac698f379f7780d | |
| parent | 332cf5327fa090ce39089e29881e2c2effb753a4 (diff) | |
| download | tinycc-e03306d1709d13d2e67349d42488a93abc4dc32a.tar.gz tinycc-e03306d1709d13d2e67349d42488a93abc4dc32a.tar.bz2 | |
tccelf: allow multiple declaration of bss/common symbols
also in combination with one initialized:
For example
1.c
int xxx;
2.c
int xxx = 2;
3.c
int xxx;
tcc 1.c 2.c 3.c
| -rw-r--r-- | tccelf.c | 13 |
1 files changed, 8 insertions, 5 deletions
@@ -236,11 +236,14 @@ ST_FUNC int add_elf_sym(Section *s, addr_t value, unsigned long size, /* keep first-found weak definition, ignore subsequents */ } else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) { /* ignore hidden symbols after */ - } else if (esym->st_shndx == SHN_COMMON - && (sh_num < SHN_LORESERVE || sh_num == SHN_COMMON)) { - /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01 - No idea if this is the correct solution ... */ + } else if ((esym->st_shndx == SHN_COMMON + || esym->st_shndx == bss_section->sh_num) + && (sh_num < SHN_LORESERVE + && sh_num != bss_section->sh_num)) { + /* data symbol gets precedence over common/bss */ goto do_patch; + } else if (sh_num == SHN_COMMON || sh_num == bss_section->sh_num) { + /* data symbol keeps precedence over common/bss */ } else if (s == tcc_state->dynsymtab_section) { /* we accept that two DLL define the same symbol */ } else { @@ -248,7 +251,7 @@ ST_FUNC int add_elf_sym(Section *s, addr_t value, unsigned long size, printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n", sym_bind, sh_num, new_vis, esym_bind, esym->st_shndx, esym_vis); #endif - tcc_error_noabort("'%s' defined twice... may be -fcommon is needed?", name); + tcc_error_noabort("'%s' defined twice", name); } } else { do_patch: |
