aboutsummaryrefslogtreecommitdiff
path: root/tccgen.c
diff options
context:
space:
mode:
authorMichael Matz <matz@suse.de>2016-10-03 19:21:10 +0200
committerMichael Matz <matz@suse.de>2016-12-15 17:47:12 +0100
commit7ab35c6265425a81c14bc313eb4c834985a73ddb (patch)
tree6d7a57c36b357befa9e9ae71856f529aa640674c /tccgen.c
parent0bca6cab06405ede5343bc22f8571b1a88aa8c22 (diff)
downloadtinycc-7ab35c6265425a81c14bc313eb4c834985a73ddb.tar.gz
tinycc-7ab35c6265425a81c14bc313eb4c834985a73ddb.tar.bz2
struct-init: Copy relocs for compound literals
When copying the content of compound literals we must include relocations as well.
Diffstat (limited to 'tccgen.c')
-rw-r--r--tccgen.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/tccgen.c b/tccgen.c
index f9d4a7c..79ec789 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -5995,9 +5995,35 @@ static void init_putv(CType *type, Section *sec, unsigned long c)
/* These come from compound literals, memcpy stuff over. */
Section *ssec;
ElfW(Sym) *esym;
+ ElfW_Rel *rel;
esym = &((ElfW(Sym) *)symtab_section->data)[vtop->sym->c];
ssec = tcc_state->sections[esym->st_shndx];
memmove (ptr, ssec->data + esym->st_value, size);
+ if (ssec->reloc) {
+ /* We need to copy over all memory contents, and that
+ includes relocations. Use the fact that relocs are
+ created it order, so look from the end of relocs
+ until we hit one before the copied region. */
+ int num_relocs = ssec->reloc->data_offset / sizeof(*rel);
+ rel = (ElfW_Rel*)(ssec->reloc->data + ssec->reloc->data_offset);
+ while (num_relocs--) {
+ rel--;
+ if (rel->r_offset >= esym->st_value + size)
+ continue;
+ if (rel->r_offset < esym->st_value)
+ break;
+ put_elf_reloca(symtab_section, sec,
+ c + rel->r_offset - esym->st_value,
+ ELFW(R_TYPE)(rel->r_info),
+ ELFW(R_SYM)(rel->r_info),
+#if defined(TCC_TARGET_ARM64) || defined(TCC_TARGET_X86_64)
+ rel->r_addend
+#else
+ 0
+#endif
+ );
+ }
+ }
} else {
if ((vtop->r & VT_SYM) &&
(bt == VT_BYTE ||