aboutsummaryrefslogtreecommitdiff
path: root/tccelf.c
diff options
context:
space:
mode:
authorThomas Preud'homme <robotux@celest.fr>2013-10-29 22:10:02 +0800
committerThomas Preud'homme <robotux@celest.fr>2013-10-29 22:10:02 +0800
commit1c4afd13501f07a673aed5f130166f2ee0f30927 (patch)
tree01d8f2a1455cd0b0cf8036a129418361207a6e6c /tccelf.c
parent3b07a15fd12d5452bf539cd855edde8139db1686 (diff)
downloadtinycc-1c4afd13501f07a673aed5f130166f2ee0f30927.tar.gz
tinycc-1c4afd13501f07a673aed5f130166f2ee0f30927.tar.bz2
Add support for thread-local storage variables
Diffstat (limited to 'tccelf.c')
-rw-r--r--tccelf.c29
1 files changed, 21 insertions, 8 deletions
diff --git a/tccelf.c b/tccelf.c
index 8af4bb6..4602ce8 100644
--- a/tccelf.c
+++ b/tccelf.c
@@ -1543,6 +1543,7 @@ static int elf_output_file(TCCState *s1, const char *filename)
int fd, mode, ret;
int *section_order;
int shnum, i, phnum, file_offset, offset, size, j, sh_order_index, k;
+ int have_tls_section = 0;
long long tmp;
addr_t addr;
Section *strsec, *s;
@@ -1861,6 +1862,11 @@ static int elf_output_file(TCCState *s1, const char *filename)
/* we output all sections if debug or object file */
s->sh_size = s->data_offset;
}
+ /* if tls section we'll need to add one segment */
+ if (s->sh_flags & SHF_TLS) {
+ have_tls_section = 1;
+ phnum++;
+ }
}
/* allocate program segment headers */
@@ -1904,12 +1910,16 @@ static int elf_output_file(TCCState *s1, const char *filename)
if (interp)
ph += 1 + HAVE_PHDR;
- for(j = 0; j < 2; j++) {
- ph->p_type = PT_LOAD;
- if (j == 0)
- ph->p_flags = PF_R | PF_X;
+ for(j = 0; j < 2 + have_tls_section; j++) {
+ if (j != 2)
+ ph->p_type = PT_LOAD;
else
- ph->p_flags = PF_R | PF_W;
+ ph->p_type = PT_TLS;
+ ph->p_flags = PF_R;
+ if (j == 0)
+ ph->p_flags |= PF_X;
+ else if (j == 1)
+ ph->p_flags |= PF_W;
ph->p_align = s1->section_align;
/* we do the following ordering: interp, symbol tables,
@@ -1920,13 +1930,16 @@ static int elf_output_file(TCCState *s1, const char *filename)
s = s1->sections[i];
/* compute if section should be included */
if (j == 0) {
- if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
+ if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE | SHF_TLS)) !=
SHF_ALLOC)
continue;
- } else {
- if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
+ } else if (j == 1) {
+ if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE | SHF_TLS)) !=
(SHF_ALLOC | SHF_WRITE))
continue;
+ } else {
+ if ((s->sh_flags & SHF_TLS) != SHF_TLS)
+ continue;
}
if (s == interp) {
if (k != 0)